# 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:
# 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'The set of atoms is similar to %s, but it is missing %d extra particles. You can add them with Modeller.addExtraParticles().'%(bestMatchName,numBestMatchAtoms-numResidueAtoms)
return'The set of atoms is similar to %s, but it is missing %d atoms.'%(bestMatchName,numBestMatchAtoms-numResidueAtoms)
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'):
makeSystem(pdbLines[:8]+pdbLines[9:])
# 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 F',
]+pdbLines[9:])
# 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 F',
]+pdbLines[9:])
# 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 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 extra site too many'):
makeSystem(pdbLines[:9]+[
'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.*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 extra site too many'):
makeSystem(pdbLines[:10]+[
'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'):
makeSystem(pdbLines[:10]+[
'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 too many'):
makeSystem(pdbLines+[
'CONECT 6 12'
])
# Remove an external bond to NME by renaming its N 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',
]+pdbLines[14:])
# Add an extra external bond to NME.
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+[
'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"""