Skip to content

Commit

Permalink
Add library charge checks
Browse files Browse the repository at this point in the history
  • Loading branch information
IAlibay committed Sep 14, 2024
1 parent 3e40419 commit 2268c1b
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/pontibus/components/extended_solvent_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
_from_dict,
GufeTokenizable,
)
from pontibus.utils.systems import WATER
from pontibus.utils.molecules import WATER


class ExtendedSolventComponent(SolventComponent):
Expand Down
45 changes: 41 additions & 4 deletions src/pontibus/tests/utils/test_interchange_packmol.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
_get_offmol_resname,
)
from pontibus.utils.systems import WATER
from numpy.testing import assert_almost_equal


@pytest.fixture()
Expand All @@ -30,8 +31,8 @@ def smc_components_benzene(benzene_modifications):


@pytest.fixture()
def methane():
m = Molecule.from_smiles("C")
def methanol():
m = Molecule.from_smiles("CO")
m.generate_conformers()
m.assign_partial_charges(partial_charge_method="gasteiger")
return m
Expand Down Expand Up @@ -110,7 +111,7 @@ def test_solv_but_no_solv_offmol(

def test_solv_mismatch(
smc_components_benzene,
methane,
methanol,
):
assert ExtendedSolventComponent().smiles == "[H][O][H]"
with pytest.raises(ValueError, match="does not match"):
Expand All @@ -120,7 +121,7 @@ def test_solv_mismatch(
smc_components=smc_components_benzene,
protein_component=None,
solvent_component=ExtendedSolventComponent(),
solvent_offmol=methane,
solvent_offmol=methanol,
)


Expand Down Expand Up @@ -161,6 +162,42 @@ def test_vacuum(smc_components_benzene):
assert len(bond) == 3


def test_noncharge_librarycharges(smc_components_benzene):
solvent_offmol = Molecule.from_smiles('O')
interchange, comp_resids = interchange_packmol_creation(
ffsettings=InterchangeFFSettings(),
solvation_settings=PackmolSolvationSettings(),
smc_components=smc_components_benzene,
protein_component=None,
solvent_component=SolventComponent(
smiles='O', neutralize=False,
ion_concentration=0 * unit.molar,
),
solvent_offmol=solvent_offmol,
)


def test_noncharge_nolibrarycharges(smc_components_benzene):
solvent_offmol = Molecule.from_smiles('c1ccccc1')
#solvent_offmol.generate_conformers()
#solvent_offmol.assign_partial_charges(partial_charge_method="gasteiger")
interchange, comp_resids = interchange_packmol_creation(
ffsettings=InterchangeFFSettings(
forcefields=["openff-2.0.0.offxml",]
),
solvation_settings=PackmolSolvationSettings(),
smc_components=smc_components_benzene,
protein_component=None,
solvent_component=SolventComponent(
smiles='c1ccccc1', neutralize=False,
ion_concentration=0 * unit.molar,
),
solvent_offmol=solvent_offmol,
)

mol = list(interchange.topology.molecules)[-1]
assert assert_almost_equal(np.array(mol.partial_charges), [0 for i in range(12)])

"""
4. Named solvent
5. Unamed solvent
Expand Down
File renamed without changes.
32 changes: 30 additions & 2 deletions src/pontibus/utils/system_creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,31 @@ def _get_offmol_resname(offmol: OFFMolecule) -> Optional[str]:
return resname


def _check_library_charges(
force_field: ForceField,
offmol: OFFMolecule,
) -> None:
"""
Check that library charges exists for an input molecule.
force_field : openff.toolkit.ForceField
Force Field object with library charges.
offmol : openff.toolkit.Molecule
Molecule to check for matching library charges.
Raises
------
ValueError
If no library charges are found for the molecule.
"""
handler = force_field.get_parameter_handler('LibraryCharges')
matches = handler.find_matches(offmol.to_topology())

if len(matches) == 0:
errmsg = f"No library charges found for {offmol}"
raise ValueError(errmsg)


def interchange_packmol_creation(
ffsettings: InterchangeFFSettings,
solvation_settings: PackmolSolvationSettings,
Expand Down Expand Up @@ -163,7 +188,7 @@ def interchange_packmol_creation(
raise ValueError(errmsg)

# 2. Get the force field object
# force_fields is a list so we unpack it
# forcefields is a list so we unpack it
force_field = ForceField(*ffsettings.forcefields)

# We also set nonbonded cutoffs whilst we are here
Expand All @@ -177,7 +202,7 @@ def interchange_packmol_creation(
# Note: comp_resnames is dict[str, tuple[Component, list]] where the final
# list is to append residues later on
# TODO: we should be able to rely on offmol equality in the same way that
# intecharge does
# intechange does
comp_resnames: dict[str, tuple[Component, list[Any]]] = {}

# If we have solvent, we set its residue name
Expand Down Expand Up @@ -225,6 +250,9 @@ def interchange_packmol_creation(
# otherwise we rely on library charges
if solvation_settings.assign_solvent_charges:
charged_mols.append(solvent_offmol)
else:
# Make sure we have library charges for the molecule
_check_library_charges(force_field, solvent_offmol)

# Pick up the user selected box shape
box_shape = {
Expand Down

0 comments on commit 2268c1b

Please sign in to comment.