Describe the bug
After converting T4-protein.pdb -> mol2 using ambertools (tleap) and applying create_openmm_system, an error from OpenMM says the formal charge is -55, which does not match the sum of mol2 partial charges of 8.
To Reproduce
Pull/switch to branch fix-491 (#509) and run pytest -k test_parameterize_protein test_forcefield.py from the tests directory,
or, from the tests directory and downloading the mol2 T4-protein.mol2.zip:
import openforcefield
from openforcefield.topology import Molecule, Topology
from openforcefield.typing.engines.smirnoff import ForceField
mol_path = 'T4-protein.mol2'
molecule = Molecule.from_file(mol_path, allow_undefined_stereo=True)
topology = Topology.from_molecules(molecule)
forcefield = ForceField('test_forcefields/smirnoff99Frosst.offxml')
omm_system = forcefield.create_openmm_system(topology, charge_from_molecules=[molecule], allow_nonintegral_charges=False)
Output
openforcefield/tests/test_forcefield.py:1886:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
openforcefield/typing/engines/smirnoff/forcefield.py:1142: in create_openmm_system
parameter_handler.postprocess_system(system, topology, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <openforcefield.typing.engines.smirnoff.parameters.ElectrostaticsHandler object at 0x7f1b6cb46320>
system = <simtk.openmm.openmm.System; proxy of <Swig Object of type 'OpenMM::System *' at 0x7f1b8ebcb7b0> >
topology = <openforcefield.topology.topology.Topology object at 0x7f1b6e128eb8>
kwargs = {'charge_from_molecules': [Molecule with name 'default_name' and SMILES '[H+].[H][C@-]1[C-]([C-]([C-]([C-]([C-]1[H])C(...])[O-])[O-])[O-])[O-])[H])[H])[H]'], 'toolkit_registry': <class 'openforcefield.utils.toolkits.OpenEyeToolkitWrapper'>}
force = <simtk.openmm.openmm.NonbondedForce; proxy of <Swig Object of type 'OpenMM::NonbondedForce *' at 0x7f1b60f473c0> >
uncharged_mols = []
ref_mol = Molecule with name 'default_name' and SMILES '[H+].[H][C@-]1[C-]([C-]([C-]([C-]([C-]1[H])C([H])([H])[C@@]([H])([C+](N(...])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[H])[H])[H]'
msg = "Partial charge sum (8.000000746455044 e) for molecule 'default_name' (SMILES [H+].[H][C@-]1[C-]([C-]([C-]([C-]([C-]1[...(-55). To override this error, provide the 'allow_nonintegral_charges=True' keyword to ForceField.create_openmm_system"
allow_nonintegral_charges = False, top_mol = <openforcefield.topology.topology.TopologyMolecule object at 0x7f1b60704550>
formal_charge_sum = -55
def postprocess_system(self, system, topology, **kwargs):
force = super().create_force(system, topology, **kwargs)
# Check to ensure all molecules have had charges assigned
uncharged_mols = []
for ref_mol in topology.reference_molecules:
if not self.check_charges_assigned(ref_mol, topology):
uncharged_mols.append(ref_mol)
if len(uncharged_mols) != 0:
msg = "The following molecules did not have charges assigned by any ParameterHandler in the ForceField:\n"
for ref_mol in uncharged_mols:
msg += f"{ref_mol.to_smiles()}\n"
raise UnassignedMoleculeChargeException(msg)
# Unless check is disabled, ensure that the sum of partial charges on a molecule
# add up to approximately its formal charge
allow_nonintegral_charges = kwargs.get('allow_nonintegral_charges', False)
for top_mol in topology.topology_molecules:
# Skip check if user manually disables it.
if allow_nonintegral_charges:
continue
formal_charge_sum = top_mol.reference_molecule.total_charge
partial_charge_sum = 0. * unit.elementary_charge
for top_particle in top_mol.particles:
q, _, _ = force.getParticleParameters(top_particle.topology_particle_index)
partial_charge_sum += q
if abs(float(formal_charge_sum) - (partial_charge_sum/unit.elementary_charge)) > 0.01:
msg = f"Partial charge sum ({partial_charge_sum}) " \
f"for molecule '{top_mol.reference_molecule.name}' (SMILES " \
f"{top_mol.reference_molecule.to_smiles()} does not equal formal charge sum " \
f"({formal_charge_sum}). To override this error, provide the " \
f"'allow_nonintegral_charges=True' keyword to ForceField.create_openmm_system"
> raise NonintegralMoleculeChargeException(msg)
E openforcefield.typing.engines.smirnoff.parameters.NonintegralMoleculeChargeException: Partial charge sum (8.000000746455044 e) for molecule 'default_name' (SMILES [H+].[H][C@-]1[C-]([C-]([C-]([C-]([C-]1[H])C([H])([H])[C@@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])C([H])([H])[C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N2[C@](C(C(C2([H])[H])([H])[H])([H])[H])([H])[C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])C([H])([H])[C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])C([H])([H])[C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])C([H])([H])[C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N3[C@](C(C(C3([H])[H])([H])[H])([H])[H])([H])[C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])C([H])([H])[C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+](N([H])[C@]([H])([C+]([O-])[O-])C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])C([H])([H])[C+](N([H])[H])[O-])[O-])C([H])([H])C([H])([H])C([H])([H])C([H])([H])[N+]([H])([H])[H])[O-])C([H])([H])[C-]4[C-]([C-]([C+]([C-]([C-]4[H])[H])O[H])[H])[H])[O-])C([H])([H])[H])[O-])C([H])([H])[C+]([O-])[O-])[O-])C([H])([H])[C-]5[C-]6[C-]([C-]([C-]([C-]([C+]6N([C+]5[H])[H])[H])[H])[H])[H])[O-])[C@@]([H])(C([H])([H])[H])O[H])[O-])[O-])[C@@]([H])(C([H])([H])[H])O[H])[O-])C([H])([H])C([H])([H])C([H])([H])N([H])[C+](N([H])[H])N([H])[H])[O-])C([H])([H])[C-]7[C-]([C-]([C-]([C-]([C-]7[H])[H])[H])[H])[H])[O-])[C@@]([H])(C([H])([H])[H])O[H])[O-])[C@@]([H])(C([H])([H])[H])O[H])[O-])[C@@]([H])(C([H])([H])[H])C([H])([H])C([H])([H])[H])[O-])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])C([H])([H])C([H])([H])C([H])([H])N([H])[C+](N([H])[H])N([H])[H])[O-])C([H])([H])C([H])([H])C([H])([H])C([H])([H])[N+]([H])([H])[H])[O-])C([H])([H])[H])[O-])C([H])([H])C([H])([H])C([H])([H])N([H])[C+](N([H])[H])N([H])[H])[O-])C([H])([H])[C+](N([H])[H])[O-])[O-])[O-])[C@@]([H])(C([H])([H])[H])O[H])[O-])C([H])([H])C([H])([H])[C+](N([H])[H])[O-])[O-])C([H])([H])[C+](N([H])[H])[O-])[O-])C([H])([H])[C-]8[C-]([C@-]([C+]([C@-]([C-]8[H])[H])O[H])[H])[H])[O-])C([H])([H])[C-]9[C-]1[C-]([C-]([C-]([C-]([C+]1N([C+]9[H])[H])[H])[H])[H])[H])[O-])C([H])([H])C([H])([H])C([H])([H])N([H])[C+](N([H])[H])N([H])[H])[O-])C([H])([H])O[H])[O-])C([H])([H])C([H])([H])C([H])([H])C([H])([H])[N+]([H])([H])[H])[O-])C([H])([H])[H])[O-])C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])C([H])([H])[C+](N([H])[H])[O-])[O-])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])C([H])([H])[H])[O-])C([H])([H])[H])[O-])C([H])([H])C([H])([H])[C+]([O-])[O-])[O-])C([H])([H])[C+]([O-])[O-])[O-])C([H])([H])[C-]1[C-]2[C@@-]([C-]([C-]([C-]([C+]2N([C+]1[H])[H])[H])[H])[H])[H])[O-])C([H])([H])C([H])([H])C([H])([H])N([H])[C+](N([H])[H])N([H])[H])[O-])C([H])([H])C([H])([H])C([H])([H])C([H])([H])[N+]([H])([H])[H])[O-])C([H])([H])C([H])([H])[C+](N([H])[H])[O-])[O-])C([H])([H])C([H])([H])[C+](N([H])[H])[O-])[O-])C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])C([H])([H])C([H])([H])SC([H])([H])[H])[O-])C([H])([H])C([H])([H])C([H])([H])N([H])[C+](N([H])[H])N([H])[H])[O-])C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])C([H])([H])O[H])[O-])C([H])([H])[C+](N([H])[H])[O-])[O-])[C@@]([H])(C([H])([H])[H])O[H])[O-])C([H])([H])[C-]1[C-]([C-]([C-]([C-]([C-]1[H])[H])[H])[H])[H])[O-])[O-])C([H])([H])[H])[O-])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])[O-])[C@@]([H])(C([H])([H])[H])O[H])[O-])C([H])([H])C([H])([H])[C+]([O-])[O-])[O-])[O-])C([H])([H])C([H])([H])SC([H])([H])[H])[O-])C([H])([H])C([H])([H])[C+](N([H])[H])[O-])[O-])C([H])([H])[C-]1[C-]([C-]([C-]([C-]([C-]1[H])[H])[H])[H])[H])[O-])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])C([H])([H])C([H])([H])SC([H])([H])[H])[O-])C([H])([H])[C+](N([H])[H])[O-])[O-])[C@@]([H])(C([H])([H])[H])C([H])([H])C([H])([H])[H])[O-])C([H])([H])[H])[O-])C([H])([H])[H])[O-])C([H])([H])S[H])[O-])C([H])([H])C([H])([H])C([H])([H])N([H])[C+](N([H])[H])N([H])[H])[O-])C([H])([H])C([H])([H])C([H])([H])N([H])[C+](N([H])[H])N([H])[H])[O-])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])C([H])([H])[H])[O-])C([H])([H])[C+]([O-])[O-])[O-])C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])C([H])([H])O[H])[O-])C([H])([H])[C+]([O-])[O-])[O-])C([H])([H])[C-]1[C-]([C-]([C+]([C-]([C-]1[H])[H])O[H])[H])[H])[O-])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])[O-])C([H])([H])C([H])([H])C([H])([H])C([H])([H])[N+]([H])([H])[H])[O-])C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])C([H])([H])C([H])([H])C([H])([H])C([H])([H])[N+]([H])([H])[H])[O-])C([H])([H])[H])[O-])C([H])([H])[C+](N([H])[H])[O-])[O-])C([H])([H])C([H])([H])C([H])([H])N([H])[C+](N([H])[H])N([H])[H])[O-])C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])[C@@]([H])(C([H])([H])[H])C([H])([H])C([H])([H])[H])[O-])[O-])C([H])([H])C([H])([H])C([H])([H])N([H])[C+](N([H])[H])N([H])[H])[O-])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])C([H])([H])[H])[O-])C([H])([H])[H])[O-])C([H])([H])[C+]([O-])[O-])[O-])C([H])(C([H])([H])[H])C([H])([H])[H])[O-])C([H])([H])[C+]([O-])[O-])[O-])C([H])([H])C([H])([H])[C+](N([H])[H])[O-])[O-])C([H])([H])[C+](N([H])[H])[O-])[O-])N([H])[C+]([C@]([H])(C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])C([H])([H])C([H])([H])[N+]([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])[C+]([O-])[O-])N([H])[C+]([C@]([H])(C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])[C+]([O-])[O-])N([H])[C+]([C@]([H])(C([H])([H])[C+]([O-])[O-])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])C([H])([H])C([H])([H])[N+]([H])([H])[H])N([H])[C+]([C@]([H])([C@@]([H])(C([H])([H])[H])O[H])N([H])[C+]([C@]([H])([C@@]([H])(C([H])([H])[H])C([H])([H])C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])(C([H])([H])[H])C([H])([H])[H])N([H])[C+](C([H])([H])N([H])[C+]([C@]([H])(C([H])([H])[C+](N([H])[H])[O-])N([H])[C+]([C@]([H])(C([H])([H])S[H])N([H])[C+]([C@]([H])(C([H])([H])[C+](N([H])[H])[O-])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])C([H])([H])N([H])[C+](N([H])[H])N([H])[H])N([H])[C+](C([H])([H])N([H])[C+]([C@]([H])([C@@]([H])(C([H])([H])[H])C([H])([H])C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])C([H])([H])C([H])([H])[N+]([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])[C+]([O-])[O-])N([H])[C+]([C@]([H])(C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])[C+]([O-])[O-])N([H])[C+]([C@]([H])(C([H])([H])O[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])C([H])([H])C([H])([H])[N+]([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])[C+](N([H])[H])[O-])N([H])[C+]([C@]([H])(C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])O[H])N([H])[C+]([C@@]1(C(C(C(N1[C+]([C@]([H])(C([H])([H])O[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])C([H])([H])C([H])([H])[N+]([H])([H])[H])N([H])[C+]([C@]([H])([C@@]([H])(C([H])([H])[H])O[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])[C+]1[C+](N([C+]([N-]1)[H])[H])[H])N([H])[C+](C([H])([H])N([H])[C+]([C@]([H])([C@@]([H])(C([H])([H])[H])C([H])([H])C([H])([H])[H])N([H])[C+](C([H])([H])N([H])[C+]([C@]([H])([C@@]([H])(C([H])([H])[H])C([H])([H])C([H])([H])[H])N([H])[C+]([C@]([H])([C@@]([H])(C([H])([H])[H])O[H])N([H])[C+]([C@]([H])(C([H])([H])[C-]1[C-]([C-]([C+]([C-]([C-]1[H])[H])O[H])[H])[H])N([H])[C+]([C@]([H])(C([H])([H])[C-]1[C-]([C-]([C+]([C-]([C-]1[H])[H])O[H])[H])[H])N([H])[C+](C([H])([H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])[C+]([O-])[O-])N([H])[C+]([C@]([H])([C@@]([H])(C([H])([H])[H])O[H])N([H])[C+]([C@]([H])(C([H])([H])[C+]([O-])[O-])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])C([H])([H])C([H])([H])[N+]([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])[C-]1[C-]([C-]([C+]([C-]([C-]1[H])[H])O[H])[H])[H])N([H])[C+]([C@]([H])([C@@]([H])(C([H])([H])[H])C([H])([H])C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])C([H])([H])C([H])([H])[N+]([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])C([H])([H])N([H])[C+](N([H])[H])N([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])N([H])[C+](C([H])([H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])[C+]([O-])[O-])N([H])[C+]([C@]([H])(C([H])([H])[C+]([O-])[O-])N([H])[C+]([C@]([H])([C@@]([H])(C([H])([H])[H])C([H])([H])C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])C([H])([H])N([H])[C+](N([H])[H])N([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])(C([H])([H])[H])C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])SC([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])[C+]([O-])[O-])N([H])[C+]([C@]([H])(C([H])([H])[C-]1[C@-]([C-]([C-]([C-]([C-]1[H])[H])[H])[H])[H])N([H])[C+]([C@]([H])([C@@]([H])(C([H])([H])[H])C([H])([H])C([H])([H])[H])N([H])[C+]([C@]([H])(C([H])([H])[C+](N([H])[H])[O-])N([H])[C+]([C@]([H])(C([H])([H])C([H])([H])SC([H])([H])[H])[N+]([H])([H])[H])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])([H])[H])([H])[H])([H])[H])[H])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[O-])[H])[H])[H] does not equal formal charge sum (-55). To override this error, provide the 'allow_nonintegral_charges=True' keyword to ForceField.create_openmm_system
Additional context
Found this while working on #491 (see PR #509). In the mol2 file, I did change the terminal residues to name NME (from MET) and CLE (from LEU). Not sure where all those O- are coming from.
@trevorgokey : How did you generate this mol2 file? It seems to have significant issues.
I was wondering why you needed to allow_undefined_stereo=True. If you don't,
molecule = Molecule.from_file(mol_path, allow_undefined_stereo=False)
it gives tons of problematic atoms
openforcefield.utils.toolkits.UndefinedStereochemistryError: Unable to make OFFMol from OEMol: OEMol has unspecified stereochemistry. oemol.GetTitle(): default_name
Problematic atoms are:
Atom atomic num: 6, name: CD1, idx: 61, aromatic: False, chiral: True with bonds:
bond order: 1, chiral: False to atom atomic num: 1, name: HD1, idx: 62, aromatic: False, chiral: False
bond order: 1, chiral: False to atom atomic num: 6, name: CE1, idx: 63, aromatic: False, chiral: True
bond order: 1, chiral: False to atom atomic num: 6, name: CG, idx: 60, aromatic: False, chiral: False
Atom atomic num: 6, name: CE1, idx: 63, aromatic: False, chiral: True with bonds:
bond order: 1, chiral: False to atom atomic num: 1, name: HE1, idx: 64, aromatic: False, chiral: False
bond order: 1, chiral: False to atom atomic num: 6, name: CZ, idx: 65, aromatic: False, chiral: False
bond order: 1, chiral: False to atom atomic num: 6, name: CD1, idx: 61, aromatic: False, chiral: True
...
These are ring atoms in a phenylalanine, which _should_ be aromatic. This suggests something is likely wrong in the bonds section.
Sure enough, all the bonds in the bonds section of the mol2 file are single bonds:
@<TRIPOS>BOND
1 18 19 1
2 18 21 1
3 14 15 1
4 14 16 1
5 14 17 1
6 13 14 1
7 10 11 1
8 10 12 1
9 10 13 1
10 7 8 1
11 7 9 1
12 7 10 1
13 5 6 1
14 5 7 1
15 5 18 1
16 1 2 1
17 1 3 1
18 1 4 1
19 1 5 1
20 33 34 1
21 33 35 1
22 30 31 1
23 30 32 1
24 28 29 1
25 28 30 1
...
Can we replace this file with a corrected mol2 file?
This is likely also the origin of the "bug". The sum of the partial charges correctly reports the net charge as +8:
>>> m = Molecule.from_file('T4-protein.mol2', allow_undefined_stereo=True)
>>> m.partial_charges.sum()
Quantity(value=8.000000746455044, unit=elementary charge)
but to avoid issues with limited precision in reporting the true integral charge of the molecule, the .total_charge property sums up formal charges, which will be incorrect because the bond orders are all incorrect, leading to incorrect valences for most atoms:
>>> m.total_charge
-55
This leads to an idea for a simple sanity check: If the sum of the partial charges and the formal charges differ by a significant fraction of an integer, there is something wrong with the valences, and we should throw an exception on molecule validation. Perhaps we could suggest this in a new issue?
Tagging @j-wags for further input.
Yes, thanks for the catch. I commented/fixed this in #509. OpenMM is raising an exception because the two are different. I think we can close this one, but the main issue now is what happens when we supply a bogus mol2 file (like I did), and need to figure out what is wrong. I think somehow validating mol2 bond orders can be done, just not sure at the moment how to do so.
I agree that we can close this. For future reference, there's 0.01*elementary charge of wiggle room before the OFF Toolkit raises a NonIntegralMoleculeChargeException
Most helpful comment
This is likely also the origin of the "bug". The sum of the partial charges correctly reports the net charge as +8:
but to avoid issues with limited precision in reporting the true integral charge of the molecule, the
.total_chargeproperty sums up formal charges, which will be incorrect because the bond orders are all incorrect, leading to incorrect valences for most atoms:This leads to an idea for a simple sanity check: If the sum of the partial charges and the formal charges differ by a significant fraction of an integer, there is something wrong with the valences, and we should throw an exception on molecule validation. Perhaps we could suggest this in a new issue?
Tagging @j-wags for further input.