Skip to content

Commit

Permalink
Merge pull request #356 from OpenBioSim/sync_exscientia
Browse files Browse the repository at this point in the history
Synchronise with Exscientia remote
  • Loading branch information
lohedges authored Oct 24, 2024
2 parents 85e7f36 + 0365150 commit e84a422
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/Sandpit_exs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:

- name: Install dependency
run: |
conda install -c conda-forge -c openbiosim/label/main biosimspace python=3.10 ambertools gromacs "sire=2024.1.0" "alchemlyb>=2.1" pytest openff-interchange pint=0.21 rdkit "jaxlib>0.3.7" tqdm
conda install -c conda-forge -c openbiosim/label/main biosimspace python=3.10 ambertools gromacs "sire=2024.2.0" "alchemlyb>=2.1" pytest openff-interchange pint=0.21 rdkit "jaxlib>0.3.7" tqdm
python -m pip install git+https://github.com/Exscientia/MDRestraintsGenerator.git
# For the testing of BSS.FreeEnergy.AlchemicalFreeEnergy.analysis
python -m pip install https://github.com/alchemistry/alchemtest/archive/master.zip
Expand Down
55 changes: 46 additions & 9 deletions python/BioSimSpace/Sandpit/Exscientia/Process/_gromacs.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from sire.legacy import Units as _SireUnits
from sire.legacy import Vol as _SireVol

from ..Units.Length import angstrom
from .._Utils import _assert_imported, _have_imported, _try_import

# alchemlyb isn't available on all variants of Python that we support, so we
Expand Down Expand Up @@ -355,7 +356,13 @@ def _write_system(self, system, coord_file=None, topol_file=None, ref_file=None)
# For now, we'll not attempt to generate a box if the system property
# is missing. If no box is present, we'll assume a non-periodic simulation.
if "space" in system._sire_object.propertyKeys():
has_box = True
try:
# Make sure that we have a periodic box. The system will now have
# a default cartesian space.
box = system._sire_object.property("space")
has_box = box.isPeriodic()
except:
has_box = False
else:
_warnings.warn("No simulation box found. Assuming gas phase simulation.")
has_box = False
Expand Down Expand Up @@ -2174,15 +2181,17 @@ def _add_position_restraints(self, config_options):
for idx, mol_idx in enumerate(mol_idxs):
# Get the indices of any restrained atoms in this molecule,
# making sure that indices are relative to the molecule.
if restraint is not None:
if restraint is None:
atom_idxs = []
elif self._system.getMolecule(mol_idx).isLipid():
atom_idxs = []
else:
atom_idxs = self._system.getRestraintAtoms(
restraint,
mol_index=mol_idx,
is_absolute=False,
allow_zero_matches=True,
)
else:
atom_idxs = []

if self._system.getMolecule(mol_idx).isAlchemicalIon():
alch_ion = self._system.getMolecule(mol_idx).getAtoms()
Expand Down Expand Up @@ -2696,8 +2705,22 @@ def _getFinalFrame(self):
)

# If this is a vacuum simulation, then translate the centre of mass
# of the system back to the origin.
if not space_prop in old_system._sire_object.propertyKeys():
# of the system back to the middle of the box to preserve PBC.
if old_system.getBox() == (None, None):
try:
old_box = old_system._sire_object.property(space_prop)
except:
old_box = None
box = _SireVol.PeriodicBox(_SireMaths.Vector(9999, 9999, 9999))
old_system._sire_object.setProperty(space_prop, box)
com = [angstrom * 9999 / 2 for _ in range(3)]
old_system.translate([x for x in com])
old_system._sire_object.make_whole()
old_system.translate([-x for x in com])
if old_box is None:
old_system._sire_object.removeProperty(space_prop)
else:
old_system._sire_object.setProperty(space_prop, old_box)
com = old_system._getCenterOfMass()
old_system.translate([-x for x in com])

Expand Down Expand Up @@ -2813,9 +2836,23 @@ def _getFrame(self, time):
)

# If this is a vacuum simulation, then translate the centre of mass
# of the system back to the origin.
if not space_prop in old_system._sire_object.propertyKeys():
com = new_system._getCenterOfMass()
# of the system back to the middle of the box to preserve PBC.
if old_system.getBox() == (None, None):
try:
old_box = old_system._sire_object.property(space_prop)
except:
old_box = None
box = _SireVol.PeriodicBox(_SireMaths.Vector(9999, 9999, 9999))
old_system._sire_object.setProperty(space_prop, box)
com = [angstrom * 9999 / 2 for _ in range(3)]
old_system.translate([x for x in com])
old_system._sire_object.make_whole()
old_system.translate([-x for x in com])
if old_box is None:
old_system._sire_object.removeProperty(space_prop)
else:
old_system._sire_object.setProperty(space_prop, old_box)
com = old_system._getCenterOfMass()
old_system.translate([-x for x in com])

return old_system
Expand Down
2 changes: 1 addition & 1 deletion python/BioSimSpace/Sandpit/Exscientia/Protocol/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def generateAmberConfig(self, extra_options=None, extra_lines=None):

# Define some miscellaneous defaults.
protocol_dict = {
"ntpr": 200, # Interval between reporting energies.
"ntpr": self._report_interval, # Interval between reporting energies.
"ntwr": self._restart_interval, # Interval between saving restart files.
"ntwx": self._restart_interval, # Trajectory sampling frequency.
"ntxo": 2, # Output coordinates as NetCDF.
Expand Down
16 changes: 16 additions & 0 deletions python/BioSimSpace/Sandpit/Exscientia/_SireWrappers/_molecule.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,22 @@ def isDecoupled(self):
else:
return False

def isLipid(self):
"""
Whether this molecule is decoupled, i.e. it can be used in a
free-energy decoupling simulation.
Returns
-------
is_decoupled : bool
Whether the molecule is decoupled.
"""
if self._sire_object.hasProperty("lipid"):
return True
else:
return False

def isML(self):
"""
Whether this molecule is marked as ML molecule, i.e. it can be used in a
Expand Down
31 changes: 31 additions & 0 deletions tests/Sandpit/Exscientia/Process/test_position_restraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,37 @@ def test_gromacs(protocol, system, ref_system, tmp_path):
assert len(diff)


@pytest.mark.skipif(
has_gromacs is False or has_openff is False,
reason="Requires GROMACS and openff to be installed",
)
@pytest.mark.parametrize("lipid", [True, False])
def test_gromacs_lipid(system, tmp_path, lipid):
protocol = BSS.Protocol.Minimisation(restraint="heavy")
if lipid:
molecule = system.getMolecule(0)
sire_obj = molecule._sire_object
c = sire_obj.cursor()
c["lipid"] = True
molecule._sire_object = c.commit()
system.updateMolecule(0, molecule)
BSS.Process.Gromacs(
system,
protocol,
reference_system=system,
work_dir=str(tmp_path),
ignore_warnings=True,
)
if lipid is False:
assert (tmp_path / "posre_0001.itp").is_file()
with open(tmp_path / "gromacs.top", "r") as f:
assert "posre_0001.itp" in f.read()
else:
assert not (tmp_path / "posre_0001.itp").is_file()
with open(tmp_path / "gromacs.top", "r") as f:
assert not "posre_0001.itp" in f.read()


@pytest.mark.skipif(
has_amber is False or has_openff is False,
reason="Requires AMBER and openff to be installed",
Expand Down
19 changes: 18 additions & 1 deletion tests/Sandpit/Exscientia/_SireWrappers/test_molecule.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import BioSimSpace.Sandpit.Exscientia as BSS

from tests.Sandpit.Exscientia.conftest import url, has_amber, has_pyarrow
from tests.Sandpit.Exscientia.conftest import url, has_amber, has_openff, has_pyarrow
from tests.conftest import root_fp


Expand Down Expand Up @@ -126,3 +126,20 @@ def test_extract(system):

# Make sure the numbers are different.
assert partial_mol.number() != mol.number()


@pytest.mark.parametrize("lipid", [True, False])
@pytest.mark.skipif(
has_amber is False or has_openff is False,
reason="Requires AMBER and OpenFF to be installed.",
)
def test_lipid(lipid):
ff = "openff_unconstrained-2.0.0"
mol = BSS.Parameters.parameterise("c1ccccc1C", ff).getMolecule()
if lipid:
sire_obj = mol._sire_object
c = sire_obj.cursor()
c["lipid"] = lipid
mol._sire_object = c.commit()

assert mol.isLipid() is lipid

0 comments on commit e84a422

Please sign in to comment.