returnf'The residue matches {bestMatches[0]}, but the set of externally bonded atoms {formatDiffMessage(templatesExtBondDiffs[bestMatches[0]],formatAtomDiff)}.'
bestMatch=pickBestMatch(bestMatches)
bestMatchDiffs=templatesExtBondDiffs[bestMatch]
ifall(value<=0forvalueinbestMatchDiffs.values()):
# Special message if external bonds are missing only, not different.
specialMessage=' Is the chain missing a terminal capping group?'
else:
specialMessage=terminalMessage
returnf'The atoms and bonds in the residue match {bestMatch}, but the set of externally bonded atoms {formatDiffMessage(bestMatchDiffs,formatAtomDiff)}.{specialMessage}'
# If we have matches at this point, atoms and bonds match perfectly, so the
# connectivity must be different. If bestMatches is empty, something else
# went wrong, so return a generic error message.
ifbestMatches:
returnf'The atoms and bonds in the residue match {bestMatches[0]}, but the connectivity is different.'
# Display all possible matching templates at this point to try to help,
# since we can't give any more detailed information.
returnf'The atoms and bonds in the residue match {joinMessages(bestMatches)}, but the connectivity is different.'
return'This might mean your input topology is missing some atoms or bonds, or possibly that you are using the wrong force field.'
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The residue contains He atoms and B atoms, which are not supported by any template in the force field'):
makeSystem(pdbLines[:9]+[
'ATOM 19 X1 GLY A 2 0 0 0 He',
'ATOM 20 X2 GLY A 2 0 0 0 B',
'ATOM 21 X3 GLY A 2 0 0 0 B',
]+pdbLines[9:])
# Delete CA atom from GLY.
withself.assertRaisesRegex(ValueError,"No template found for residue.*GLY.*The set of atoms is similar to GLY, but is missing 1 C atom"):
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The set of atoms is similar to GLY, but is missing 1 C atom'):
makeSystem(pdbLines[:8]+pdbLines[9:])
# Add an He atom to GLY.
withself.assertRaisesRegex(ValueError,"No template found for residue.*GLY.*The set of atoms is similar to GLY, but has 1 He atom extra"):
# Add an F atom to GLY.
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The set of atoms is similar to GLY, but has 1 F atom too many'):
makeSystem(pdbLines[:9]+[
"ATOM 19 X1 GLY A 2 0 0 0 He",
'ATOM 19 X1 GLY A 2 0 0 0 F',
]+pdbLines[9:])
# Delete CA atom from GLY and add an He atom.
withself.assertRaisesRegex(ValueError,"No template found for residue.*GLY.*The set of atoms is similar to GLY, but is missing 1 C atom and has 1 He atom extra"):
# Delete CA atom from GLY and add an F atom.
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The set of atoms is similar to GLY, but is missing 1 C atom and has 1 F atom too many'):
makeSystem(pdbLines[:8]+[
"ATOM 19 X1 GLY A 2 0 0 0 He",
'ATOM 19 X1 GLY A 2 0 0 0 F',
]+pdbLines[9:])
# Add 1 He atom, 2 Li atoms, and 1 Be atom to GLY.
withself.assertRaisesRegex(ValueError,"No template found for residue.*GLY.*The set of atoms is similar to GLY, but has 1 He atom, 2 Li atoms, and 1 Be atom extra"):
# Add 1 F atom, 2 Cl atoms, and 1 Br atom to GLY.
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The set of atoms is similar to GLY, but has 1 F atom, 2 Cl atoms, and 1 Br atom too many'):
makeSystem(pdbLines[:9]+[
"ATOM 19 X1 GLY A 2 0 0 0 He",
"ATOM 20 X2 GLY A 2 0 0 0 Li",
"ATOM 21 X3 GLY A 2 0 0 0 Li",
"ATOM 22 X4 GLY A 2 0 0 0 Be",
'ATOM 19 X1 GLY A 2 0 0 0 F',
'ATOM 20 X2 GLY A 2 0 0 0 Cl',
'ATOM 21 X3 GLY A 2 0 0 0 Cl',
'ATOM 22 X4 GLY A 2 0 0 0 Br',
]+pdbLines[9:])
# Add a virtual site to GLY.
withself.assertRaisesRegex(ValueError,"No template found for residue.*GLY.*The set of heavy atoms matches GLY, but the residue has 1 site extra"):
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The set of heavy atoms matches GLY, but the residue has 1 extra site too many'):
makeSystem(pdbLines[:9]+[
"ATOM 19 X1 GLY A 2 0 0 0 EP",
'ATOM 19 X1 GLY A 2 0 0 0 EP',
]+pdbLines[9:])
# Delete HA3 atom from GLY.
withself.assertRaisesRegex(ValueError,"No template found for residue.*GLY.*The set of heavy atoms matches GLY, but the residue is missing 1 H atom"):
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The set of heavy atoms matches GLY, but the residue is missing 1 H atom.*You may be able to add it with.*addHydrogens'):
makeSystem(pdbLines[:10]+pdbLines[11:])
# Delete HA2 and HA3 atoms from GLY.
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The set of heavy atoms matches GLY, but the residue is missing 2 H atoms.*You may be able to add them with.*addHydrogens'):
makeSystem(pdbLines[:9]+pdbLines[11:])
# Delete HA3 atom from GLY and add a virtual site.
withself.assertRaisesRegex(ValueError,"No template found for residue.*GLY.*The set of heavy atoms matches GLY, but the residue is missing 1 H atom and has 1 site extra"):
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The set of heavy atoms matches GLY, but the residue is missing 1 H atom and has 1 extra site too many'):
makeSystem(pdbLines[:10]+[
"ATOM 19 X1 GLY A 2 0 0 0 EP",
'ATOM 19 X1 GLY A 2 0 0 0 EP',
]+pdbLines[11:])
# Rename HA3 atom to remove the CA-HA3 bond.
withself.assertRaisesRegex(ValueError,"No template found for residue.*GLY.*The set of atoms matches GLY, but the residue is missing 1 H-C bond"):
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The set of atoms matches GLY, but the residue is missing 1 H-C bond'):
makeSystem(pdbLines[:10]+[
"ATOM 10 X1 GLY A 2 0 0 0 H",
'ATOM 10 X1 GLY A 2 0 0 0 H',
]+pdbLines[11:])
# Add an extra N-O bond.
withself.assertRaisesRegex(ValueError,"No template found for residue.*GLY.*The set of atoms matches GLY, but the residue has 1 N-O bond extra"):
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The set of atoms matches GLY, but the residue has 1 N-O bond too many'):
makeSystem(pdbLines+[
"CONECT 6 12"
'CONECT 6 12'
])
# Remove an external bond to NME by renaming its N atom.
withself.assertRaisesRegex(ValueError,"No template found for residue.*GLY.*The residue matches GLY, but the set of externally bonded atoms is missing 1 C atom"):
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The atoms and bonds in the residue match GLY, but the set of externally bonded atoms is missing 1 C atom'):
makeSystem(pdbLines[:13]+[
"ATOM 13 X1 NME A 3 0 0 0 N",
'ATOM 13 X1 NME A 3 0 0 0 N',
]+pdbLines[14:])
# Add an extra external bond to NME.
withself.assertRaisesRegex(ValueError,"No template found for residue.*GLY.*The residue matches GLY, but the set of externally bonded atoms has 1 O atom extra"):
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The atoms and bonds in the residue match GLY, but the set of externally bonded atoms has 1 O atom too many'):
makeSystem(pdbLines+[
'CONECT 12 15'
])
# Delete ACE so that a capping group is missing from GLY.
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The atoms and bonds in the residue match GLY, but the set of externally bonded atoms is missing 1 N atom.*Is the chain missing a terminal capping group?'):
makeSystem(pdbLines[6:])
# Keep the atom/bond element fingerprint the same but change the connectivity.
withself.assertRaisesRegex(ValueError,'No template found for residue.*GLY.*The atoms and bonds in the residue match GLY, but the connectivity is different'):
# Rename O to break the C=O bond, but then reattach the O to the CA.
makeSystem(pdbLines[:12]+[
'ATOM 12 X1 GLY A 2 0 0 0 O',
]+pdbLines[13:]+[
'CONECT 8 12'
])
# Make water with incorrect atom names so bonds will be missing.
pdbLines=[
'ATOM 0 X1 HOH A 1 0 0 0 O',
'ATOM 1 X2 HOH A 1 0 0 0 H',
'ATOM 2 X3 HOH A 1 0 0 0 H',
]
# Check for a special message when all bonds are missing.
forcefield=ForceField('opc3.xml')
withself.assertRaisesRegex(ValueError,'No template found for residue.*HOH.*The set of atoms matches HOH, but the residue has no bonds between its atoms'):
makeSystem(pdbLines)
# Add a site to a residue with a force field that doesn't support sites.
withself.assertRaisesRegex(ValueError,'No template found for residue.*HOH.*The residue contains extra sites, which are not supported by any template in the force field'):
makeSystem(pdbLines+[
"CONECT 12 15"
'ATOM 3 X4 HOH A 1 0 0 0 EP',
])
# Load a force field so that 1 site will be missing.
forcefield=ForceField('opc.xml')
withself.assertRaisesRegex(ValueError,'No template found for residue.*HOH.*The set of heavy atoms matches HOH, but the residue is missing 1 extra site.*You may be able to add it with.*addExtraParticles'):
makeSystem(pdbLines)
# Load a force field so that 2 sites will be missing.
forcefield=ForceField('tip5p.xml')
withself.assertRaisesRegex(ValueError,'No template found for residue.*HOH.*The set of heavy atoms matches HOH, but the residue is missing 2 extra sites.*You may be able to add them with.*addExtraParticles'):
makeSystem(pdbLines)
# Use an empty force field so that there are no templates.
forcefield=ForceField()
withself.assertRaisesRegex(ValueError,'No template found for residue.*HOH.*The force field contains no residue templates'):
makeSystem(pdbLines)
deftest_Wildcard(self):
"""Test that PeriodicTorsionForces using wildcard ('') for atom types / classes in the ffxml are correctly registered"""