Commit 39120086 authored by John Chodera (MSKCC)'s avatar John Chodera (MSKCC)
Browse files

Merge remote-tracking branch 'upstream/master' into forcefield

parents 87b95319 2acba7ad
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010 Stanford University and the Authors. *
* Portions copyright (c) 2010-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -45,6 +45,7 @@ void testSerialization() {
// Create a Force.
AmoebaBondForce force1;
force1.setForceGroup(3);
force1.setAmoebaGlobalBondCubic(12.3);
force1.setAmoebaGlobalBondQuartic(98.7);
force1.addBond(0, 1, 1.0, 2.0);
......@@ -60,6 +61,7 @@ void testSerialization() {
// Compare the two forces to see if they are identical.
AmoebaBondForce& force2 = *copy;
ASSERT_EQUAL(force1.getForceGroup(), force2.getForceGroup());
ASSERT_EQUAL(force1.getAmoebaGlobalBondCubic(), force2.getAmoebaGlobalBondCubic());
ASSERT_EQUAL(force1.getAmoebaGlobalBondQuartic(), force2.getAmoebaGlobalBondQuartic());
ASSERT_EQUAL(force1.getNumBonds(), force2.getNumBonds());
......
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010 Stanford University and the Authors. *
* Portions copyright (c) 2010-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -45,6 +45,7 @@ void testSerialization() {
// Create a Force.
AmoebaGeneralizedKirkwoodForce force1;
force1.setForceGroup(3);
force1.setSolventDielectric( 80.0);
force1.setSoluteDielectric( 1.0);
//force1.setDielectricOffset( 0.09);
......@@ -64,6 +65,7 @@ void testSerialization() {
// Compare the two forces to see if they are identical.
AmoebaGeneralizedKirkwoodForce& force2 = *copy;
ASSERT_EQUAL(force1.getForceGroup(), force2.getForceGroup());
ASSERT_EQUAL(force1.getSolventDielectric(), force2.getSolventDielectric());
ASSERT_EQUAL(force1.getSoluteDielectric(), force2.getSoluteDielectric());
//ASSERT_EQUAL(force1.getDielectricOffset(), force2.getDielectricOffset());
......
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010 Stanford University and the Authors. *
* Portions copyright (c) 2010-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -46,6 +46,7 @@ void testSerialization() {
AmoebaInPlaneAngleForce force1;
force1.setForceGroup(3);
force1.setAmoebaGlobalInPlaneAngleCubic(12.3);
force1.setAmoebaGlobalInPlaneAngleQuartic(98.7);
force1.setAmoebaGlobalInPlaneAnglePentic(91.7);
......@@ -65,6 +66,7 @@ void testSerialization() {
// Compare the two forces to see if they are identical.
AmoebaInPlaneAngleForce& force2 = *copy;
ASSERT_EQUAL(force1.getForceGroup(), force2.getForceGroup());
ASSERT_EQUAL(force1.getAmoebaGlobalInPlaneAngleCubic(), force2.getAmoebaGlobalInPlaneAngleCubic());
ASSERT_EQUAL(force1.getAmoebaGlobalInPlaneAngleQuartic(), force2.getAmoebaGlobalInPlaneAngleQuartic());
ASSERT_EQUAL(force1.getAmoebaGlobalInPlaneAnglePentic(), force2.getAmoebaGlobalInPlaneAnglePentic());
......
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010 Stanford University and the Authors. *
* Portions copyright (c) 2010-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -59,6 +59,7 @@ void testSerialization() {
// Create a Force.
AmoebaMultipoleForce force1;
force1.setForceGroup(3);
force1.setNonbondedMethod(AmoebaMultipoleForce::NoCutoff);
force1.setCutoffDistance(0.9);
force1.setAEwald(0.544);
......@@ -74,6 +75,12 @@ void testSerialization() {
force1.setMutualInducedTargetEpsilon(1.0e-05);
//force1.setElectricConstant(138.93);
force1.setEwaldErrorTolerance(1.0e-05);
vector<double> coeff;
coeff.push_back(0.0);
coeff.push_back(-0.1);
coeff.push_back(1.1);
force1.setExtrapolationCoefficients(coeff);
std::vector<std::string> covalentTypes;
getCovalentTypes(covalentTypes);
......@@ -105,6 +112,7 @@ void testSerialization() {
// Compare the two forces to see if they are identical.
AmoebaMultipoleForce& force2 = *copy;
ASSERT_EQUAL(force1.getForceGroup(), force2.getForceGroup());
ASSERT_EQUAL(force1.getCutoffDistance(), force2.getCutoffDistance());
ASSERT_EQUAL(force1.getNonbondedMethod(), force2.getNonbondedMethod());
ASSERT_EQUAL(force1.getAEwald(), force2.getAEwald());
......@@ -125,6 +133,8 @@ void testSerialization() {
ASSERT_EQUAL(gridDimension1[jj], gridDimension2[jj]);
}
ASSERT_EQUAL_CONTAINERS(force1.getExtrapolationCoefficients(), force2.getExtrapolationCoefficients());
ASSERT_EQUAL(force1.getNumMultipoles(), force2.getNumMultipoles());
for (unsigned int ii = 0; ii < static_cast<unsigned int>(force1.getNumMultipoles()); ii++) {
......
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010 Stanford University and the Authors. *
* Portions copyright (c) 2010-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -46,6 +46,7 @@ void testSerialization() {
AmoebaOutOfPlaneBendForce force1;
force1.setForceGroup(3);
force1.setAmoebaGlobalOutOfPlaneBendCubic(12.3);
force1.setAmoebaGlobalOutOfPlaneBendQuartic(98.7);
force1.setAmoebaGlobalOutOfPlaneBendPentic(91.7);
......@@ -65,6 +66,7 @@ void testSerialization() {
// Compare the two forces to see if they are identical.
AmoebaOutOfPlaneBendForce& force2 = *copy;
ASSERT_EQUAL(force1.getForceGroup(), force2.getForceGroup());
ASSERT_EQUAL(force1.getAmoebaGlobalOutOfPlaneBendCubic(), force2.getAmoebaGlobalOutOfPlaneBendCubic());
ASSERT_EQUAL(force1.getAmoebaGlobalOutOfPlaneBendQuartic(), force2.getAmoebaGlobalOutOfPlaneBendQuartic());
ASSERT_EQUAL(force1.getAmoebaGlobalOutOfPlaneBendPentic(), force2.getAmoebaGlobalOutOfPlaneBendPentic());
......
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010 Stanford University and the Authors. *
* Portions copyright (c) 2010-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -45,6 +45,7 @@ void testSerialization() {
// Create a Force.
AmoebaPiTorsionForce force1;
force1.setForceGroup(3);
force1.addPiTorsion(0, 1, 3, 4, 5, 6, 2.0);
force1.addPiTorsion(0, 2, 3, 5, 12, 13, 2.1);
force1.addPiTorsion(2, 3, 5, 6, 81, 91, 2.2);
......@@ -58,6 +59,7 @@ void testSerialization() {
// Compare the two forces to see if they are identical.
AmoebaPiTorsionForce& force2 = *copy;
ASSERT_EQUAL(force1.getForceGroup(), force2.getForceGroup());
ASSERT_EQUAL(force1.getNumPiTorsions(), force2.getNumPiTorsions());
for (unsigned int ii = 0; ii < static_cast<unsigned int>(force1.getNumPiTorsions()); ii++) {
int a1, a2, a3, a4, a5, a6, b1, b2, b3, b4, b5, b6;
......
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010 Stanford University and the Authors. *
* Portions copyright (c) 2010-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -45,6 +45,7 @@ void testSerialization() {
// Create a Force.
AmoebaStretchBendForce force1;
force1.setForceGroup(3);
force1.addStretchBend(0, 1, 3, 1.0, 1.2, 150.1, 83.2, 100.);
force1.addStretchBend(2, 4, 4, 1.1, 2.2, 180.1, 89.2, 100.);
force1.addStretchBend(5, 0, 1, 3.1, 8.2, 140.1, 98.2, 100.);
......@@ -57,6 +58,7 @@ void testSerialization() {
// Compare the two forces to see if they are identical.
AmoebaStretchBendForce& force2 = *copy;
ASSERT_EQUAL(force1.getForceGroup(), force2.getForceGroup());
ASSERT_EQUAL(force1.getNumStretchBends(), force2.getNumStretchBends());
for (unsigned int ii = 0; ii < static_cast<unsigned int>(force1.getNumStretchBends()); ii++) {
int p11, p12, p13;
......
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010 Stanford University and the Authors. *
* Portions copyright (c) 2010-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -81,6 +81,7 @@ void testSerialization() {
AmoebaTorsionTorsionForce force1;
force1.setForceGroup(3);
for (unsigned int ii = 0; ii < 5; ii++) {
std::vector< std::vector< std::vector<double> > > gridVector;
loadTorsionTorsionGrid(gridVector);
......@@ -99,6 +100,7 @@ void testSerialization() {
// Compare the two force1s to see if they are identical.
AmoebaTorsionTorsionForce & force2 = *copy;
ASSERT_EQUAL(force1.getForceGroup(), force2.getForceGroup());
ASSERT_EQUAL(force1.getNumTorsionTorsions(), force2.getNumTorsionTorsions());
for (unsigned int ii = 0; ii < static_cast<unsigned int>(force1.getNumTorsionTorsions()); ii++) {
......
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010 Stanford University and the Authors. *
* Portions copyright (c) 2010-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -45,6 +45,7 @@ void testSerialization() {
// Create a Force.
AmoebaVdwForce force1;
force1.setForceGroup(3);
force1.setSigmaCombiningRule("GEOMETRIC");
force1.setEpsilonCombiningRule("GEOMETRIC");
force1.setCutoff(0.9);
......@@ -70,6 +71,7 @@ void testSerialization() {
// Compare the two forces to see if they are identical.
AmoebaVdwForce& force2 = *copy;
ASSERT_EQUAL(force1.getForceGroup(), force2.getForceGroup());
ASSERT_EQUAL(force1.getSigmaCombiningRule(), force2.getSigmaCombiningRule());
ASSERT_EQUAL(force1.getEpsilonCombiningRule(), force2.getEpsilonCombiningRule());
ASSERT_EQUAL(force1.getCutoff(), force2.getCutoff());
......
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010 Stanford University and the Authors. *
* Portions copyright (c) 2010-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -45,6 +45,7 @@ void testSerialization() {
// Create a Force.
AmoebaWcaDispersionForce force1;
force1.setForceGroup(3);
force1.setEpso( 1.0);
force1.setEpsh( 1.1);
force1.setRmino( 1.2);
......@@ -68,6 +69,7 @@ void testSerialization() {
AmoebaWcaDispersionForce& force2 = *copy;
ASSERT_EQUAL(force1.getForceGroup(), force2.getForceGroup());
ASSERT_EQUAL(force1.getEpso(), force2.getEpso());
ASSERT_EQUAL(force1.getEpsh(), force2.getEpsh());
ASSERT_EQUAL(force1.getRmino(), force2.getRmino());
......
......@@ -64,7 +64,8 @@ void CustomCentroidBondForceProxy::serialize(const void* object, SerializationNo
for (int j = 0; j < (int) particles.size(); j++) {
SerializationNode& node = group.createChildNode("Particle");
node.setIntProperty("p", particles[j]);
node.setDoubleProperty("weight", weights[j]);
if (j < weights.size())
node.setDoubleProperty("weight", weights[j]);
}
}
SerializationNode& bonds = node.createChildNode("Bonds");
......@@ -115,7 +116,8 @@ void* CustomCentroidBondForceProxy::deserialize(const SerializationNode& node) c
vector<double> weights;
for (int j = 0; j < (int) group.getChildren().size(); j++) {
particles.push_back(group.getChildren()[j].getIntProperty("p"));
weights.push_back(group.getChildren()[j].getDoubleProperty("weight"));
if (group.getChildren()[j].hasProperty("weight"))
weights.push_back(group.getChildren()[j].getDoubleProperty("weight"));
}
force->addGroup(particles, weights);
}
......
......@@ -51,7 +51,8 @@ void testSerialization() {
vector<double> weights;
for (int j = 0; j < i+1; j++) {
particles.push_back(i+j);
weights.push_back(1.0/(i+1));
if (i < 2)
weights.push_back(1.0/(i+1));
}
force.addGroup(particles, weights);
}
......
......@@ -220,6 +220,7 @@
<Variant name="HID"/>
<Variant name="HIE"/>
<Variant name="HIP"/>
<Variant name="HIN"/>
<H name="H" parent="N"/>
<H name="H2" parent="N" terminal="N"/>
<H name="H3" parent="N" terminal="N"/>
......
......@@ -3760,6 +3760,8 @@ class AmoebaMultipoleGenerator:
polarizationType = args['polarization']
if (polarizationType.lower() == 'direct'):
force.setPolarizationType(mm.AmoebaMultipoleForce.Direct)
elif (polarizationType.lower() == 'extrapolated'):
force.setPolarizationType(mm.AmoebaMultipoleForce.Extrapolated)
else:
force.setPolarizationType(mm.AmoebaMultipoleForce.Mutual)
......
......@@ -123,7 +123,7 @@ class PdbStructure(object):
"""
def __init__(self, input_stream, load_all_models=False):
def __init__(self, input_stream, load_all_models=False, extraParticleIdentifier='EP'):
"""Create a PDB model from a PDB file stream.
Parameters
......@@ -135,9 +135,12 @@ class PdbStructure(object):
load_all_models : bool
Whether to load every model of an NMR structure or trajectory, or
just load the first model, to save memory.
extraParticleIdentifier : string='EP'
if this value appears in the element column for an ATOM record, the Atom's element will be set to 'EP' to mark it as an extra particle
"""
# initialize models
self.load_all_models = load_all_models
self.extraParticleIdentifier = extraParticleIdentifier
self.models = []
self._current_model = None
self.default_model = None
......@@ -157,7 +160,7 @@ class PdbStructure(object):
pdb_line = pdb_line.decode('utf-8')
# Look for atoms
if (pdb_line.find("ATOM ") == 0) or (pdb_line.find("HETATM") == 0):
self._add_atom(Atom(pdb_line, self))
self._add_atom(Atom(pdb_line, self, self.extraParticleIdentifier))
# Notice MODEL punctuation, for the next level of detail
# in the structure->model->chain->residue->atom->position hierarchy
elif (pdb_line.find("MODEL") == 0):
......@@ -682,7 +685,7 @@ class Residue(object):
class Atom(object):
"""Atom represents one atom in a PDB structure.
"""
def __init__(self, pdb_line, pdbstructure=None):
def __init__(self, pdb_line, pdbstructure=None, extraParticleIdentifier='EP'):
"""Create a new pdb.Atom from an ATOM or HETATM line.
Example line:
......@@ -795,11 +798,14 @@ class Atom(object):
try: self.formal_charge = int(pdb_line[78:80])
except ValueError: self.formal_charge = None
# figure out atom element
try:
# Try to find a sensible element symbol from columns 76-77
self.element = element.get_by_symbol(self.element_symbol)
except KeyError:
self.element = None
if self.element_symbol == extraParticleIdentifier:
self.element = 'EP'
else:
try:
# Try to find a sensible element symbol from columns 76-77
self.element = element.get_by_symbol(self.element_symbol)
except KeyError:
self.element = None
if pdbstructure is not None:
pdbstructure._next_atom_number = self.serial_number+1
pdbstructure._next_residue_number = self.residue_number+1
......
......@@ -6,7 +6,7 @@ Simbios, the NIH National Center for Physics-Based Simulation of
Biological Structures at Stanford, funded under the NIH Roadmap for
Medical Research, grant U54 GM072970. See https://simtk.org.
Portions copyright (c) 2012-2015 Stanford University and the Authors.
Portions copyright (c) 2012-2016 Stanford University and the Authors.
Authors: Peter Eastman
Contributors:
......@@ -614,6 +614,7 @@ class Modeller(object):
HID: Neutral form with a hydrogen on the ND1 atom
HIE: Neutral form with a hydrogen on the NE2 atom
HIP: Positively charged form with hydrogens on both ND1 and NE2
HIN: Negatively charged form without a hydrogen on either ND1 or NE2
Lysine:
LYN: Neutral form with two hydrogens on the zeta nitrogen
......@@ -625,9 +626,14 @@ class Modeller(object):
2. Any Cysteine that participates in a disulfide bond uses the CYX variant regardless of pH.
3. For a neutral Histidine residue, the HID or HIE variant is selected based on which one forms a better hydrogen bond.
You can override these rules by explicitly specifying a variant for any residue. Also keep in mind that this
function will only add hydrogens. It will never remove ones that are already present in the model, regardless
of the specified pH.
You can override these rules by explicitly specifying a variant for any residue. To do that, provide a list for the
'variants' parameter, and set the corresponding element to the name of the variant to use.
A special case is when the model already contains a hydrogen that should not be present in the desired variant.
If you explicitly specify a variant using the 'variants' parameter, the residue will be modified to match the
desired variant, removing hydrogens if necessary. On the other hand, for residues whose variant is selected
automatically, this function will only add hydrogens. It will never remove ones that are already present in the
model, regardless of the specified pH.
Definitions for standard amino acids and nucleotides are built in. You can call loadHydrogenDefinitions() to load
additional definitions for other residue types.
......@@ -771,6 +777,7 @@ class Modeller(object):
if variant is not None and variant not in spec.variants:
raise ValueError('Illegal variant for %s residue: %s' % (residue.name, variant))
actualVariants[residue.index] = variant
removeExtraHydrogens = (variants[residue.index] is not None)
# Make a list of hydrogens that should be present in the residue.
......@@ -783,6 +790,11 @@ class Modeller(object):
# Loop over atoms in the residue, adding them to the new topology along with required hydrogens.
for parent in residue.atoms():
# Check whether this is a hydrogen that should be removed.
if removeExtraHydrogens and parent.element == elem.hydrogen and not any(parent.name == h.name for h in hydrogens):
continue
# Add the atom.
newAtom = newTopology.addAtom(parent.name, parent.element, newResidue)
......
......@@ -59,7 +59,7 @@ class PDBFile(object):
_residueNameReplacements = {}
_atomNameReplacements = {}
def __init__(self, file):
def __init__(self, file, extraParticleIdentifier='EP'):
"""Load a PDB file.
The atom positions and Topology can be retrieved by calling getPositions() and getTopology().
......@@ -68,6 +68,8 @@ class PDBFile(object):
----------
file : string
the name of the file to load
extraParticleIdentifier : string='EP'
if this value appears in the element column for an ATOM record, the Atom's element will be set to None to mark it as an extra particle
"""
metalElements = ['Al','As','Ba','Ca','Cd','Ce','Co','Cs','Cu','Dy','Fe','Gd','Hg','Ho','In','Ir','K','Li','Mg',
......@@ -91,7 +93,7 @@ class PDBFile(object):
if isinstance(file, str):
inputfile = open(file)
own_handle = True
pdb = PdbStructure(inputfile, load_all_models=True)
pdb = PdbStructure(inputfile, load_all_models=True, extraParticleIdentifier=extraParticleIdentifier)
if own_handle:
inputfile.close()
PDBFile._loadNameReplacementTables()
......@@ -116,7 +118,9 @@ class PDBFile(object):
atomName = atomReplacements[atomName]
atomName = atomName.strip()
element = atom.element
if element is None:
if element == 'EP':
element = None
elif element is None:
# Try to guess the element.
upper = atomName.upper()
......@@ -253,7 +257,7 @@ class PDBFile(object):
map[atom.attrib[id]] = name
@staticmethod
def writeFile(topology, positions, file=sys.stdout, keepIds=False):
def writeFile(topology, positions, file=sys.stdout, keepIds=False, extraParticleIdentifier=' '):
"""Write a PDB file containing a single model.
Parameters
......@@ -269,9 +273,11 @@ class PDBFile(object):
rather than generating new ones. Warning: It is up to the caller to
make sure these are valid IDs that satisfy the requirements of the
PDB format. Otherwise, the output file will be invalid.
extraParticleIdentifier : string=' '
String to write in the element column of the ATOM records for atoms whose element is None (extra particles)
"""
PDBFile.writeHeader(topology, file)
PDBFile.writeModel(topology, positions, file, keepIds=keepIds)
PDBFile.writeModel(topology, positions, file, keepIds=keepIds, extraParticleIdentifier=extraParticleIdentifier)
PDBFile.writeFooter(topology, file)
@staticmethod
......@@ -294,7 +300,7 @@ class PDBFile(object):
a*10, b*10, c*10, alpha*RAD_TO_DEG, beta*RAD_TO_DEG, gamma*RAD_TO_DEG), file=file)
@staticmethod
def writeModel(topology, positions, file=sys.stdout, modelIndex=None, keepIds=False):
def writeModel(topology, positions, file=sys.stdout, modelIndex=None, keepIds=False, extraParticleIdentifier=' '):
"""Write out a model to a PDB file.
Parameters
......@@ -313,6 +319,8 @@ class PDBFile(object):
rather than generating new ones. Warning: It is up to the caller to
make sure these are valid IDs that satisfy the requirements of the
PDB format. Otherwise, the output file will be invalid.
extraParticleIdentifier : string=' '
String to write in the element column of the ATOM records for atoms whose element is None (extra particles)
"""
if len(list(topology.atoms())) != len(positions):
......@@ -343,17 +351,17 @@ class PDBFile(object):
else:
resId = "%4d" % ((resIndex+1)%10000)
for atom in res.atoms():
if len(atom.name) < 4 and atom.name[:1].isalpha() and (atom.element is None or len(atom.element.symbol) < 2):
if atom.element is not None:
symbol = atom.element.symbol
else:
symbol = extraParticleIdentifier
if len(atom.name) < 4 and atom.name[:1].isalpha() and len(symbol) < 2:
atomName = ' '+atom.name
elif len(atom.name) > 4:
atomName = atom.name[:4]
else:
atomName = atom.name
coords = positions[posIndex]
if atom.element is not None:
symbol = atom.element.symbol
else:
symbol = ' '
line = "ATOM %5d %-4s %3s %s%4s %s%s%s 1.00 0.00 %2s " % (
atomIndex%100000, atomName, resName, chainName, resId, _format_83(coords[0]),
_format_83(coords[1]), _format_83(coords[2]), symbol)
......
......@@ -247,6 +247,7 @@ UNITS = {
("AmoebaMultipoleForce", "getPmeBSplineOrder") : ( None,()),
("AmoebaMultipoleForce", "getMutualInducedMaxIterations") : ( None, ()),
("AmoebaMultipoleForce", "getMutualInducedTargetEpsilon") : ( None, ()),
("AmoebaMultipoleForce", "getExtrapolationCoefficients") : ( None, ()),
("AmoebaMultipoleForce", "getEwaldErrorTolerance") : ( None, ()),
("AmoebaMultipoleForce", "getPmeGridDimensions") : ( None,()),
......
......@@ -903,6 +903,29 @@ class TestModeller(unittest.TestCase):
validate_equivalence(self, topology_LYN, topology_after)
def test_removeExtraHydrogens(self):
"""Test that addHydrogens() can remove hydrogens that shouldn't be there. """
topology_start = self.topology_start3
positions = self.positions3
modeller = Modeller(topology_start, positions)
# Add hydrogens, forcing residue 1 to be ASH.
variants = [None]*25
variants[1] = 'ASH'
modeller.addHydrogens(self.forcefield, variants=variants)
residue = list(modeller.topology.residues())[1]
self.assertTrue(any(a.name == 'HD2' for a in residue.atoms()))
# Now force it to be ASP and see if HD2 gets removed.
variants[1] = 'ASP'
modeller.addHydrogens(self.forcefield, variants=variants)
residue = list(modeller.topology.residues())[1]
self.assertFalse(any(a.name == 'HD2' for a in residue.atoms()))
def test_addExtraParticles(self):
"""Test addExtraParticles()."""
......
......@@ -70,6 +70,20 @@ class TestPdbFile(unittest.TestCase):
pdb = PDBFile(open('systems/triclinic.pdb', 'rb'))
self.assertEqual(len(pdb.positions), 8)
def test_ExtraParticles(self):
"""Test reading, and writing and re-reading of a file containing extra particle atoms."""
pdb = PDBFile('systems/tip5p.pdb')
for atom in pdb.topology.atoms():
if atom.index > 2:
self.assertEqual(None, atom.element)
output = StringIO()
PDBFile.writeFile(pdb.topology, pdb.positions, output)
input = StringIO(output.getvalue())
pdb = PDBFile(input, extraParticleIdentifier = '')
for atom in pdb.topology.atoms():
if atom.index > 2:
self.assertEqual(None, atom.element)
def assertVecAlmostEqual(self, p1, p2, tol=1e-7):
unit = p1.unit
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment