From 4ad39be86bc7f650b357f5636a0d1e164ab9f073 Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Wed, 31 Jul 2024 15:58:15 +0200 Subject: [PATCH 01/32] Start Gromacs Run Unit --- .../protocols/gromacs_md/md_methods.py | 121 +++++++++++++++++- .../protocols/gromacs_md/md_settings.py | 10 ++ 2 files changed, 124 insertions(+), 7 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index 0555f32..14ba3d5 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -54,6 +54,7 @@ OpenMMEngineSettings, OpenMMSolvationSettings, ) +import gmxapi as gmx logger = logging.getLogger(__name__) @@ -103,6 +104,7 @@ def _dict2mdp(settings_dict: dict, shared_basepath): # Remove non-mdp settings from the dictionary settings_dict.pop("forcefield_cache") settings_dict.pop("mdp_file") + settings_dict.pop("tpr_file") with open(filename, "w") as f: for key, value in settings_dict.items(): # First convert units to units in the mdp file, then remove units @@ -208,6 +210,7 @@ class GromacsMDProtocol(gufe.Protocol): result_cls = GromacsMDProtocolResult _settings: GromacsMDProtocolSettings + @classmethod def _default_settings(cls): """A dictionary of initial settings for this creating this Protocol @@ -253,12 +256,15 @@ def _default_settings(cls): ), output_settings_em=EMOutputSettings( mdp_file="em.mdp", + tpr_file="em.tpr", ), output_settings_nvt=NVTOutputSettings( mdp_file="nvt.mdp", + tpr_file="nvt.tpr", ), output_settings_npt=NPTOutputSettings( mdp_file="npt.mdp", + tpr_file="npt.tpr", nstxout=5000, nstvout=5000, nstfout=5000, @@ -306,16 +312,24 @@ def _create( # our DAG has no dependencies, so just list units n_repeats = self.settings.protocol_repeats - units = [ - GromacsMDSetupUnit( + setup = GromacsMDSetupUnit( protocol=self, stateA=stateA, generation=0, repeat_id=int(uuid.uuid4()), + name=f"{system_name}", + ) + run = [ + GromacsMDRunUnit( + protocol=self, + setup=setup, + generation=0, + repeat_id=int(uuid.uuid4()), name=f"{system_name} repeat {i} generation 0", ) for i in range(n_repeats) ] + units = [setup] + run return units @@ -371,11 +385,6 @@ def __init__( counter for how many times this repeat has been extended name : str, optional human-readable identifier for this Unit - - Notes - ----- - The mapping used must not involve any elemental changes. A check for - this is done on class creation. """ super().__init__( name=name, @@ -654,3 +663,101 @@ def _execute( "generation": self._inputs["generation"], **outputs, } + + +class GromacsMDRunUnit(gufe.ProtocolUnit): + """ + Protocol unit for running plain MD simulations (NonTransformation) + in Gromacs. + """ + def _execute( + self, + ctx: gufe.Context, + *, + protocol, + setup, + **kwargs, + ) -> dict[str, Any]: + """ + Execute the simulation part of the Gromacs MD protocol. + + Parameters + ---------- + ctx : gufe.protocols.protocolunit.Context + The gufe context for the unit. + protocol : gufe.protocols.Protocol + The Protocol used to create this Unit. Contains key + information + such as the settings. + setup : gufe.protocols.ProtocolUnit + The SetupUnit + + Returns + ------- + dict : dict[str, str] + Dictionary with paths to ... + """ + log_system_probe(logging.INFO, paths=[ctx.scratch]) + + if ctx.shared is None: + # use cwd + shared_basepath = pathlib.Path(".") + else: + shared_basepath = ctx.shared + + + # ToDo: Figure out how to specify the order in which to run things + + # Will we need the settings? Likely only if we add run settings, + # e.g. number of threads,... + # ToDo: Add output settings, e.g. name of output files + protocol_settings: GromacsMDProtocolSettings = self._inputs["protocol"].settings + sim_settings_em: EMSimulationSettings = \ + protocol_settings.simulation_settings_em + sim_settings_nvt: NVTSimulationSettings = ( + protocol_settings.simulation_settings_nvt + ) + sim_settings_npt: NPTSimulationSettings = ( + protocol_settings.simulation_settings_npt + ) + output_settings_em: EMOutputSettings = \ + protocol_settings.output_settings_em + output_settings_nvt: NVTOutputSettings = \ + protocol_settings.output_settings_nvt + output_settings_npt: NPTOutputSettings = \ + protocol_settings.output_settings_npt + + input_gro = setup.outputs["system_gro"] + input_top = setup.outputs["system_top"] + mdp_files = setup.outputs["mdp_files"] + + # Run energy minimization + print('Running EM') + import os + import subprocess + # EM + if sim_settings_em.nsteps > 0: + mdp = [x for x in mdp_files if str(x).split('/')[1] == output_settings_em.mdp_file] + tpr = ctx.shared / output_settings_em.tpr_file + assert len(mdp) == 1 + assert os.path.exists(input_gro) + assert os.path.exists(input_top) + assert os.path.exists(mdp[0]) + + + p = subprocess.Popen(['gmx', 'grompp', '-f', mdp[0], + '-c', input_gro, '-p', input_top, + '-o', tpr], + stdin=subprocess.PIPE) + p.wait() + p = subprocess.Popen(['gmx', 'mdrun', '-s', tpr.name, + '-deffnm', 'em'], + stdin=subprocess.PIPE, + cwd=ctx.shared) + p.wait() + + return { + "repeat_id": self._inputs["repeat_id"], + "generation": self._inputs["generation"], + # **outputs, + } diff --git a/openfe_gromacs/protocols/gromacs_md/md_settings.py b/openfe_gromacs/protocols/gromacs_md/md_settings.py index e3a9b07..766498f 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_settings.py +++ b/openfe_gromacs/protocols/gromacs_md/md_settings.py @@ -9,6 +9,7 @@ """ from typing import Literal, Optional +import pint from gufe.settings import OpenMMSystemGeneratorFFSettings, SettingsBaseModel from openfe.protocols.openmm_utils.omm_settings import ( IntegratorSettings, @@ -403,6 +404,7 @@ def must_be_between_3_12(cls, v): def is_time(cls, v): if not v.is_compatible_with(unit.picosecond): raise ValueError("dt must be in time units (i.e. picoseconds)") + return v @validator("rlist", "rcoulomb", "rvdw") def is_distance(cls, v): @@ -411,6 +413,7 @@ def is_distance(cls, v): "rlist, rcoulomb, and rvdw must be in distance " "units (i.e. nanometers)" ) + return v @validator("ref_t", "gen_temp") def is_temperature(cls, v): @@ -418,11 +421,13 @@ def is_temperature(cls, v): raise ValueError( "ref_t and gen_temp must be in temperature units (i.e. kelvin)" ) + return v @validator("ref_p") def is_pressure(cls, v): if not v.is_compatible_with(unit.bar): raise ValueError("ref_p must be in pressure units (i.e. bar)") + return v @validator("integrator") def supported_integrator(cls, v): @@ -451,6 +456,11 @@ class OutputSettings(SettingsBaseModel): Filename for the mdp file for running simulations in Gromacs. Default 'em.mdp' """ + tpr_file: str = 'em.tpr' + """ + Filename for the tpr file for running simulations in Gromacs. + Default 'em.tpr' + """ nstxout: int = 0 """ Number of steps that elapse between writing coordinates to the output From a734c3bc3aa0db3f8f671756a46f076a5113dad1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 13:59:14 +0000 Subject: [PATCH 02/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../protocols/gromacs_md/md_methods.py | 71 +++++++++++-------- .../protocols/gromacs_md/md_settings.py | 2 +- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index 14ba3d5..a063967 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -17,6 +17,7 @@ from collections.abc import Iterable from typing import Any, Optional +import gmxapi as gmx import gufe import pint from gufe import ( @@ -54,7 +55,6 @@ OpenMMEngineSettings, OpenMMSolvationSettings, ) -import gmxapi as gmx logger = logging.getLogger(__name__) @@ -210,7 +210,6 @@ class GromacsMDProtocol(gufe.Protocol): result_cls = GromacsMDProtocolResult _settings: GromacsMDProtocolSettings - @classmethod def _default_settings(cls): """A dictionary of initial settings for this creating this Protocol @@ -313,12 +312,12 @@ def _create( # our DAG has no dependencies, so just list units n_repeats = self.settings.protocol_repeats setup = GromacsMDSetupUnit( - protocol=self, - stateA=stateA, - generation=0, - repeat_id=int(uuid.uuid4()), - name=f"{system_name}", - ) + protocol=self, + stateA=stateA, + generation=0, + repeat_id=int(uuid.uuid4()), + name=f"{system_name}", + ) run = [ GromacsMDRunUnit( protocol=self, @@ -670,6 +669,7 @@ class GromacsMDRunUnit(gufe.ProtocolUnit): Protocol unit for running plain MD simulations (NonTransformation) in Gromacs. """ + def _execute( self, ctx: gufe.Context, @@ -677,7 +677,7 @@ def _execute( protocol, setup, **kwargs, - ) -> dict[str, Any]: + ) -> dict[str, Any]: """ Execute the simulation part of the Gromacs MD protocol. @@ -700,60 +700,71 @@ def _execute( log_system_probe(logging.INFO, paths=[ctx.scratch]) if ctx.shared is None: - # use cwd + # use cwd shared_basepath = pathlib.Path(".") else: shared_basepath = ctx.shared - # ToDo: Figure out how to specify the order in which to run things # Will we need the settings? Likely only if we add run settings, # e.g. number of threads,... # ToDo: Add output settings, e.g. name of output files protocol_settings: GromacsMDProtocolSettings = self._inputs["protocol"].settings - sim_settings_em: EMSimulationSettings = \ - protocol_settings.simulation_settings_em + sim_settings_em: EMSimulationSettings = protocol_settings.simulation_settings_em sim_settings_nvt: NVTSimulationSettings = ( protocol_settings.simulation_settings_nvt ) sim_settings_npt: NPTSimulationSettings = ( protocol_settings.simulation_settings_npt ) - output_settings_em: EMOutputSettings = \ - protocol_settings.output_settings_em - output_settings_nvt: NVTOutputSettings = \ - protocol_settings.output_settings_nvt - output_settings_npt: NPTOutputSettings = \ - protocol_settings.output_settings_npt + output_settings_em: EMOutputSettings = protocol_settings.output_settings_em + output_settings_nvt: NVTOutputSettings = protocol_settings.output_settings_nvt + output_settings_npt: NPTOutputSettings = protocol_settings.output_settings_npt input_gro = setup.outputs["system_gro"] input_top = setup.outputs["system_top"] mdp_files = setup.outputs["mdp_files"] # Run energy minimization - print('Running EM') + print("Running EM") import os import subprocess + # EM if sim_settings_em.nsteps > 0: - mdp = [x for x in mdp_files if str(x).split('/')[1] == output_settings_em.mdp_file] + mdp = [ + x + for x in mdp_files + if str(x).split("/")[1] == output_settings_em.mdp_file + ] tpr = ctx.shared / output_settings_em.tpr_file assert len(mdp) == 1 assert os.path.exists(input_gro) assert os.path.exists(input_top) assert os.path.exists(mdp[0]) - - p = subprocess.Popen(['gmx', 'grompp', '-f', mdp[0], - '-c', input_gro, '-p', input_top, - '-o', tpr], - stdin=subprocess.PIPE) + p = subprocess.Popen( + [ + "gmx", + "grompp", + "-f", + mdp[0], + "-c", + input_gro, + "-p", + input_top, + "-o", + tpr, + ], + stdin=subprocess.PIPE, + ) p.wait() - p = subprocess.Popen(['gmx', 'mdrun', '-s', tpr.name, - '-deffnm', 'em'], - stdin=subprocess.PIPE, - cwd=ctx.shared) + p = subprocess.Popen( + ["gmx", "mdrun", "-s", tpr.name, "-deffnm", "em"], + stdin=subprocess.PIPE, + cwd=ctx.shared, + ) p.wait() return { diff --git a/openfe_gromacs/protocols/gromacs_md/md_settings.py b/openfe_gromacs/protocols/gromacs_md/md_settings.py index 766498f..a439add 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_settings.py +++ b/openfe_gromacs/protocols/gromacs_md/md_settings.py @@ -456,7 +456,7 @@ class OutputSettings(SettingsBaseModel): Filename for the mdp file for running simulations in Gromacs. Default 'em.mdp' """ - tpr_file: str = 'em.tpr' + tpr_file: str = "em.tpr" """ Filename for the tpr file for running simulations in Gromacs. Default 'em.tpr' From f9a5aea9d6630b9cfb27108f5bdacaf78926d72b Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Wed, 31 Jul 2024 17:22:09 +0200 Subject: [PATCH 03/32] Add NVT, NPT --- .../protocols/gromacs_md/md_methods.py | 91 ++++++++++++------- 1 file changed, 60 insertions(+), 31 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index a063967..96950a9 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -16,7 +16,8 @@ from collections import defaultdict from collections.abc import Iterable from typing import Any, Optional - +import os +import subprocess import gmxapi as gmx import gufe import pint @@ -669,6 +670,34 @@ class GromacsMDRunUnit(gufe.ProtocolUnit): Protocol unit for running plain MD simulations (NonTransformation) in Gromacs. """ + def _run_gromacs(self, mdp, gro, top, tpr, deffnm, shared_basebath): + assert os.path.exists(gro) + assert os.path.exists(top) + assert os.path.exists(mdp) + p = subprocess.Popen( + [ + "gmx", + "grompp", + "-f", + mdp, + "-c", + gro, + "-p", + top, + "-o", + tpr, + ], + stdin=subprocess.PIPE, + ) + p.wait() + assert os.path.exists(tpr) + p = subprocess.Popen( + ["gmx", "mdrun", "-s", tpr.name, "-deffnm", deffnm], + stdin=subprocess.PIPE, + cwd=shared_basebath, + ) + p.wait() + return def _execute( self, @@ -728,10 +757,6 @@ def _execute( # Run energy minimization print("Running EM") - import os - import subprocess - - # EM if sim_settings_em.nsteps > 0: mdp = [ x @@ -739,33 +764,37 @@ def _execute( if str(x).split("/")[1] == output_settings_em.mdp_file ] tpr = ctx.shared / output_settings_em.tpr_file + deffnm = str(output_settings_em.tpr_file.split('.')[0]) assert len(mdp) == 1 - assert os.path.exists(input_gro) - assert os.path.exists(input_top) - assert os.path.exists(mdp[0]) - - p = subprocess.Popen( - [ - "gmx", - "grompp", - "-f", - mdp[0], - "-c", - input_gro, - "-p", - input_top, - "-o", - tpr, - ], - stdin=subprocess.PIPE, - ) - p.wait() - p = subprocess.Popen( - ["gmx", "mdrun", "-s", tpr.name, "-deffnm", "em"], - stdin=subprocess.PIPE, - cwd=ctx.shared, - ) - p.wait() + self._run_gromacs(mdp[0], input_gro, input_top, tpr, deffnm, ctx.shared) + + # Run NVT + print("Running NVT") + if sim_settings_nvt.nsteps > 0: + mdp = [ + x + for x in mdp_files + if str(x).split("/")[1] == output_settings_nvt.mdp_file + ] + tpr = ctx.shared / output_settings_nvt.tpr_file + deffnm = str(output_settings_nvt.tpr_file.split('.')[0]) + assert len(mdp) == 1 + self._run_gromacs(mdp[0], input_gro, input_top, tpr, deffnm, + ctx.shared) + + # Run NPT + print("Running NPT") + if sim_settings_npt.nsteps > 0: + mdp = [ + x + for x in mdp_files + if str(x).split("/")[1] == output_settings_npt.mdp_file + ] + tpr = ctx.shared / output_settings_npt.tpr_file + deffnm = str(output_settings_npt.tpr_file.split('.')[0]) + assert len(mdp) == 1 + self._run_gromacs(mdp[0], input_gro, input_top, tpr, deffnm, + ctx.shared) return { "repeat_id": self._inputs["repeat_id"], From b52d8fd48b326114c13cdb3b0fcb0591ff0fab98 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 15:22:23 +0000 Subject: [PATCH 04/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../protocols/gromacs_md/md_methods.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index 96950a9..c5d15f3 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -11,13 +11,14 @@ from __future__ import annotations import logging +import os import pathlib +import subprocess import uuid from collections import defaultdict from collections.abc import Iterable from typing import Any, Optional -import os -import subprocess + import gmxapi as gmx import gufe import pint @@ -670,6 +671,7 @@ class GromacsMDRunUnit(gufe.ProtocolUnit): Protocol unit for running plain MD simulations (NonTransformation) in Gromacs. """ + def _run_gromacs(self, mdp, gro, top, tpr, deffnm, shared_basebath): assert os.path.exists(gro) assert os.path.exists(top) @@ -764,7 +766,7 @@ def _execute( if str(x).split("/")[1] == output_settings_em.mdp_file ] tpr = ctx.shared / output_settings_em.tpr_file - deffnm = str(output_settings_em.tpr_file.split('.')[0]) + deffnm = str(output_settings_em.tpr_file.split(".")[0]) assert len(mdp) == 1 self._run_gromacs(mdp[0], input_gro, input_top, tpr, deffnm, ctx.shared) @@ -777,10 +779,9 @@ def _execute( if str(x).split("/")[1] == output_settings_nvt.mdp_file ] tpr = ctx.shared / output_settings_nvt.tpr_file - deffnm = str(output_settings_nvt.tpr_file.split('.')[0]) + deffnm = str(output_settings_nvt.tpr_file.split(".")[0]) assert len(mdp) == 1 - self._run_gromacs(mdp[0], input_gro, input_top, tpr, deffnm, - ctx.shared) + self._run_gromacs(mdp[0], input_gro, input_top, tpr, deffnm, ctx.shared) # Run NPT print("Running NPT") @@ -791,10 +792,9 @@ def _execute( if str(x).split("/")[1] == output_settings_npt.mdp_file ] tpr = ctx.shared / output_settings_npt.tpr_file - deffnm = str(output_settings_npt.tpr_file.split('.')[0]) + deffnm = str(output_settings_npt.tpr_file.split(".")[0]) assert len(mdp) == 1 - self._run_gromacs(mdp[0], input_gro, input_top, tpr, deffnm, - ctx.shared) + self._run_gromacs(mdp[0], input_gro, input_top, tpr, deffnm, ctx.shared) return { "repeat_id": self._inputs["repeat_id"], From 3761335e51b533de57b48cad2314411fdace92ed Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Thu, 1 Aug 2024 10:57:42 +0200 Subject: [PATCH 05/32] Add more output settings --- .../protocols/gromacs_md/md_methods.py | 78 ++++++++++++++----- .../protocols/gromacs_md/md_settings.py | 30 +++++++ 2 files changed, 88 insertions(+), 20 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index c5d15f3..2b31afa 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -104,9 +104,10 @@ def _dict2mdp(settings_dict: dict, shared_basepath): """ filename = shared_basepath / settings_dict["mdp_file"] # Remove non-mdp settings from the dictionary - settings_dict.pop("forcefield_cache") - settings_dict.pop("mdp_file") - settings_dict.pop("tpr_file") + non_mdps = ["forcefield_cache", "mdp_file", "tpr_file", "trr_file", + "xtc_file", "gro_file", "edr_file", "log_file", "cpt_file"] + for setting in non_mdps: + settings_dict.pop(setting) with open(filename, "w") as f: for key, value in settings_dict.items(): # First convert units to units in the mdp file, then remove units @@ -258,14 +259,32 @@ def _default_settings(cls): output_settings_em=EMOutputSettings( mdp_file="em.mdp", tpr_file="em.tpr", + gro_file="em.gro", + trr_file="em.trr", + xtc_file="em.xtc", + edr_file="em.edr", + cpt_file="em.cpt", + log_file="em.log", ), output_settings_nvt=NVTOutputSettings( mdp_file="nvt.mdp", tpr_file="nvt.tpr", + gro_file="nvt.gro", + trr_file="nvt.trr", + xtc_file="nvt.xtc", + edr_file="nvt.edr", + cpt_file="nvt.cpt", + log_file="nvt.log", ), output_settings_npt=NPTOutputSettings( mdp_file="npt.mdp", tpr_file="npt.tpr", + gro_file="npt.gro", + trr_file="npt.trr", + xtc_file="npt.xtc", + edr_file="npt.edr", + cpt_file="npt.cpt", + log_file="npt.log", nstxout=5000, nstvout=5000, nstfout=5000, @@ -672,8 +691,11 @@ class GromacsMDRunUnit(gufe.ProtocolUnit): in Gromacs. """ - def _run_gromacs(self, mdp, gro, top, tpr, deffnm, shared_basebath): - assert os.path.exists(gro) + def _run_gromacs( + self, mdp, in_gro, top, tpr, out_gro, xtc, trr, cpt, log, edr, + shared_basebath, + ): + assert os.path.exists(in_gro) assert os.path.exists(top) assert os.path.exists(mdp) p = subprocess.Popen( @@ -683,7 +705,7 @@ def _run_gromacs(self, mdp, gro, top, tpr, deffnm, shared_basebath): "-f", mdp, "-c", - gro, + in_gro, "-p", top, "-o", @@ -694,7 +716,8 @@ def _run_gromacs(self, mdp, gro, top, tpr, deffnm, shared_basebath): p.wait() assert os.path.exists(tpr) p = subprocess.Popen( - ["gmx", "mdrun", "-s", tpr.name, "-deffnm", deffnm], + ["gmx", "mdrun", "-s", tpr.name, "-cpo", cpt, "-o", trr, + "-x", xtc, "-c", out_gro, "-e", edr, "-g", log], stdin=subprocess.PIPE, cwd=shared_basebath, ) @@ -707,6 +730,7 @@ def _execute( *, protocol, setup, + verbose=True, **kwargs, ) -> dict[str, Any]: """ @@ -737,9 +761,6 @@ def _execute( shared_basepath = ctx.shared # ToDo: Figure out how to specify the order in which to run things - - # Will we need the settings? Likely only if we add run settings, - # e.g. number of threads,... # ToDo: Add output settings, e.g. name of output files protocol_settings: GromacsMDProtocolSettings = self._inputs["protocol"].settings sim_settings_em: EMSimulationSettings = protocol_settings.simulation_settings_em @@ -758,43 +779,60 @@ def _execute( mdp_files = setup.outputs["mdp_files"] # Run energy minimization - print("Running EM") if sim_settings_em.nsteps > 0: + if verbose: + self.logger.info("Running energy minimization") mdp = [ x for x in mdp_files if str(x).split("/")[1] == output_settings_em.mdp_file ] tpr = ctx.shared / output_settings_em.tpr_file - deffnm = str(output_settings_em.tpr_file.split(".")[0]) assert len(mdp) == 1 - self._run_gromacs(mdp[0], input_gro, input_top, tpr, deffnm, ctx.shared) - + #ToDo: If no traj should be written out, don't write empty file? + self._run_gromacs( + mdp[0], input_gro, input_top, tpr, output_settings_em.gro_file, + output_settings_em.xtc_file, output_settings_em.trr_file, + output_settings_em.cpt_file, output_settings_em.log_file, + output_settings_em.edr_file, ctx.shared) + + # ToDo: Should we dissallow running MD without EM? # Run NVT - print("Running NVT") if sim_settings_nvt.nsteps > 0: + if verbose: + self.logger.info("Running an NVT MD simulation") mdp = [ x for x in mdp_files if str(x).split("/")[1] == output_settings_nvt.mdp_file ] tpr = ctx.shared / output_settings_nvt.tpr_file - deffnm = str(output_settings_nvt.tpr_file.split(".")[0]) assert len(mdp) == 1 - self._run_gromacs(mdp[0], input_gro, input_top, tpr, deffnm, ctx.shared) + #ToDo: Change .gro to output from EM if we do EM first, + # else original .gro file + self._run_gromacs( + mdp[0], input_gro, input_top, tpr, output_settings_nvt.gro_file, + output_settings_nvt.xtc_file, output_settings_nvt.trr_file, + output_settings_nvt.cpt_file, output_settings_nvt.log_file, + output_settings_nvt.edr_file, ctx.shared) # Run NPT - print("Running NPT") if sim_settings_npt.nsteps > 0: + if verbose: + self.logger.info("Running an NPT MD simulation") mdp = [ x for x in mdp_files if str(x).split("/")[1] == output_settings_npt.mdp_file ] tpr = ctx.shared / output_settings_npt.tpr_file - deffnm = str(output_settings_npt.tpr_file.split(".")[0]) assert len(mdp) == 1 - self._run_gromacs(mdp[0], input_gro, input_top, tpr, deffnm, ctx.shared) + self._run_gromacs( + mdp[0], input_gro, input_top, tpr, + output_settings_npt.gro_file, + output_settings_npt.xtc_file, output_settings_npt.trr_file, + output_settings_npt.cpt_file, output_settings_npt.log_file, + output_settings_npt.edr_file, ctx.shared) return { "repeat_id": self._inputs["repeat_id"], diff --git a/openfe_gromacs/protocols/gromacs_md/md_settings.py b/openfe_gromacs/protocols/gromacs_md/md_settings.py index a439add..1e0ff86 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_settings.py +++ b/openfe_gromacs/protocols/gromacs_md/md_settings.py @@ -461,6 +461,36 @@ class OutputSettings(SettingsBaseModel): Filename for the tpr file for running simulations in Gromacs. Default 'em.tpr' """ + gro_file: str = "em.gro" + """ + Filename for the output .gro file from a Gromacs run. + Default 'em.gro' + """ + edr_file: str = "em.edr" + """ + Filename for the output energy (.edr) file from a Gromacs simulation. + Default 'em.edr' + """ + log_file: str = "em.log" + """ + Filename for the output .log file from a Gromacs simulation. + Default 'em.tpr' + """ + trr_file: str = "em.trr" + """ + Filename for the output trajectory (.trr) file from a Gromacs simulation. + Default 'em.trr' + """ + xtc_file: str = "em.xtc" + """ + Filename for the output trajectory file (.xtc) from a Gromacs simulation. + Default 'em.xtc' + """ + cpt_file: str = "em.cpt" + """ + Filename for the checkpoint file (.cpt) from a Gromacs simulation. + Default 'em.cpt' + """ nstxout: int = 0 """ Number of steps that elapse between writing coordinates to the output From 0a829e8117cb30429dcd40e1c8469e016b6da887 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 08:58:08 +0000 Subject: [PATCH 06/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../protocols/gromacs_md/md_methods.py | 98 +++++++++++++++---- 1 file changed, 78 insertions(+), 20 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index 2b31afa..436aba8 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -104,8 +104,17 @@ def _dict2mdp(settings_dict: dict, shared_basepath): """ filename = shared_basepath / settings_dict["mdp_file"] # Remove non-mdp settings from the dictionary - non_mdps = ["forcefield_cache", "mdp_file", "tpr_file", "trr_file", - "xtc_file", "gro_file", "edr_file", "log_file", "cpt_file"] + non_mdps = [ + "forcefield_cache", + "mdp_file", + "tpr_file", + "trr_file", + "xtc_file", + "gro_file", + "edr_file", + "log_file", + "cpt_file", + ] for setting in non_mdps: settings_dict.pop(setting) with open(filename, "w") as f: @@ -692,8 +701,18 @@ class GromacsMDRunUnit(gufe.ProtocolUnit): """ def _run_gromacs( - self, mdp, in_gro, top, tpr, out_gro, xtc, trr, cpt, log, edr, - shared_basebath, + self, + mdp, + in_gro, + top, + tpr, + out_gro, + xtc, + trr, + cpt, + log, + edr, + shared_basebath, ): assert os.path.exists(in_gro) assert os.path.exists(top) @@ -716,8 +735,24 @@ def _run_gromacs( p.wait() assert os.path.exists(tpr) p = subprocess.Popen( - ["gmx", "mdrun", "-s", tpr.name, "-cpo", cpt, "-o", trr, - "-x", xtc, "-c", out_gro, "-e", edr, "-g", log], + [ + "gmx", + "mdrun", + "-s", + tpr.name, + "-cpo", + cpt, + "-o", + trr, + "-x", + xtc, + "-c", + out_gro, + "-e", + edr, + "-g", + log, + ], stdin=subprocess.PIPE, cwd=shared_basebath, ) @@ -789,12 +824,20 @@ def _execute( ] tpr = ctx.shared / output_settings_em.tpr_file assert len(mdp) == 1 - #ToDo: If no traj should be written out, don't write empty file? + # ToDo: If no traj should be written out, don't write empty file? self._run_gromacs( - mdp[0], input_gro, input_top, tpr, output_settings_em.gro_file, - output_settings_em.xtc_file, output_settings_em.trr_file, - output_settings_em.cpt_file, output_settings_em.log_file, - output_settings_em.edr_file, ctx.shared) + mdp[0], + input_gro, + input_top, + tpr, + output_settings_em.gro_file, + output_settings_em.xtc_file, + output_settings_em.trr_file, + output_settings_em.cpt_file, + output_settings_em.log_file, + output_settings_em.edr_file, + ctx.shared, + ) # ToDo: Should we dissallow running MD without EM? # Run NVT @@ -808,13 +851,21 @@ def _execute( ] tpr = ctx.shared / output_settings_nvt.tpr_file assert len(mdp) == 1 - #ToDo: Change .gro to output from EM if we do EM first, + # ToDo: Change .gro to output from EM if we do EM first, # else original .gro file self._run_gromacs( - mdp[0], input_gro, input_top, tpr, output_settings_nvt.gro_file, - output_settings_nvt.xtc_file, output_settings_nvt.trr_file, - output_settings_nvt.cpt_file, output_settings_nvt.log_file, - output_settings_nvt.edr_file, ctx.shared) + mdp[0], + input_gro, + input_top, + tpr, + output_settings_nvt.gro_file, + output_settings_nvt.xtc_file, + output_settings_nvt.trr_file, + output_settings_nvt.cpt_file, + output_settings_nvt.log_file, + output_settings_nvt.edr_file, + ctx.shared, + ) # Run NPT if sim_settings_npt.nsteps > 0: @@ -828,11 +879,18 @@ def _execute( tpr = ctx.shared / output_settings_npt.tpr_file assert len(mdp) == 1 self._run_gromacs( - mdp[0], input_gro, input_top, tpr, + mdp[0], + input_gro, + input_top, + tpr, output_settings_npt.gro_file, - output_settings_npt.xtc_file, output_settings_npt.trr_file, - output_settings_npt.cpt_file, output_settings_npt.log_file, - output_settings_npt.edr_file, ctx.shared) + output_settings_npt.xtc_file, + output_settings_npt.trr_file, + output_settings_npt.cpt_file, + output_settings_npt.log_file, + output_settings_npt.edr_file, + ctx.shared, + ) return { "repeat_id": self._inputs["repeat_id"], From 7221446475f1c3a8f39942201c3e26ff4a958a6c Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Thu, 1 Aug 2024 14:02:10 +0200 Subject: [PATCH 07/32] return file paths for all Gromacs outputs --- .../protocols/gromacs_md/md_methods.py | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index 436aba8..83062ad 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -895,5 +895,25 @@ def _execute( return { "repeat_id": self._inputs["repeat_id"], "generation": self._inputs["generation"], - # **outputs, + "gro_em": shared_basepath / output_settings_em.gro_file, + "tpr_em": shared_basepath / output_settings_em.tpr_file, + "trr_em": shared_basepath / output_settings_em.trr_file, + "xtc_em": shared_basepath / output_settings_em.xtc_file, + "edr_em": shared_basepath / output_settings_em.edr_file, + "log_em": shared_basepath / output_settings_em.log_file, + "cpt_em": shared_basepath / output_settings_em.cpt_file, + "gro_nvt": shared_basepath / output_settings_nvt.gro_file, + "tpr_nvt": shared_basepath / output_settings_nvt.tpr_file, + "trr_nvt": shared_basepath / output_settings_nvt.trr_file, + "xtc_nvt": shared_basepath / output_settings_nvt.xtc_file, + "edr_nvt": shared_basepath / output_settings_nvt.edr_file, + "log_nvt": shared_basepath / output_settings_nvt.log_file, + "cpt_nvt": shared_basepath / output_settings_nvt.cpt_file, + "gro_npt": shared_basepath / output_settings_npt.gro_file, + "tpr_npt": shared_basepath / output_settings_npt.tpr_file, + "trr_npt": shared_basepath / output_settings_npt.trr_file, + "xtc_npt": shared_basepath / output_settings_npt.xtc_file, + "edr_npt": shared_basepath / output_settings_npt.edr_file, + "log_npt": shared_basepath / output_settings_npt.log_file, + "cpt_npt": shared_basepath / output_settings_npt.cpt_file, } From a075e4ca2cdfc02679d736df65d8288023db37b4 Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Mon, 5 Aug 2024 14:34:38 +0200 Subject: [PATCH 08/32] some fixes --- openfe_gromacs/protocols/gromacs_md/md_methods.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index 83062ad..dcfe9fa 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -820,9 +820,9 @@ def _execute( mdp = [ x for x in mdp_files - if str(x).split("/")[1] == output_settings_em.mdp_file + if str(x).split("/")[-1] == output_settings_em.mdp_file ] - tpr = ctx.shared / output_settings_em.tpr_file + tpr = pathlib.Path(ctx.shared / output_settings_em.tpr_file) assert len(mdp) == 1 # ToDo: If no traj should be written out, don't write empty file? self._run_gromacs( @@ -839,7 +839,7 @@ def _execute( ctx.shared, ) - # ToDo: Should we dissallow running MD without EM? + # ToDo: Should we disallow running MD without EM? # Run NVT if sim_settings_nvt.nsteps > 0: if verbose: @@ -847,9 +847,9 @@ def _execute( mdp = [ x for x in mdp_files - if str(x).split("/")[1] == output_settings_nvt.mdp_file + if str(x).split("/")[-1] == output_settings_nvt.mdp_file ] - tpr = ctx.shared / output_settings_nvt.tpr_file + tpr = pathlib.Path(ctx.shared / output_settings_nvt.tpr_file) assert len(mdp) == 1 # ToDo: Change .gro to output from EM if we do EM first, # else original .gro file @@ -874,9 +874,9 @@ def _execute( mdp = [ x for x in mdp_files - if str(x).split("/")[1] == output_settings_npt.mdp_file + if str(x).split("/")[-1] == output_settings_npt.mdp_file ] - tpr = ctx.shared / output_settings_npt.tpr_file + tpr = pathlib.Path(ctx.shared / output_settings_npt.tpr_file) assert len(mdp) == 1 self._run_gromacs( mdp[0], From e8a6796bba6ce80bf8b85a6f9e82e502f4ed01ed Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Mon, 5 Aug 2024 14:35:01 +0200 Subject: [PATCH 09/32] Changing the tests --- .../tests/protocols/test_gromacs_md.py | 232 ++++++++++-------- 1 file changed, 127 insertions(+), 105 deletions(-) diff --git a/openfe_gromacs/tests/protocols/test_gromacs_md.py b/openfe_gromacs/tests/protocols/test_gromacs_md.py index 9b987f9..3878b12 100644 --- a/openfe_gromacs/tests/protocols/test_gromacs_md.py +++ b/openfe_gromacs/tests/protocols/test_gromacs_md.py @@ -3,7 +3,7 @@ import json import pathlib from unittest import mock - +from openff.units import unit as off_unit import gufe import pytest @@ -63,13 +63,13 @@ def test_create_independent_repeat_ids(benzene_system): ) repeat_ids = set() - u: GromacsMDSetupUnit for u in dag1.protocol_units: repeat_ids.add(u.inputs["repeat_id"]) for u in dag2.protocol_units: repeat_ids.add(u.inputs["repeat_id"]) - - assert len(repeat_ids) == 6 + # This should result in 4 repeat ids per DAG, 1 GromacsMDSetupUnit and + # 3 GromacsMDRunUnits + assert len(repeat_ids) == 8 def test_no_SolventComponent(benzene_vacuum_system, tmpdir): @@ -128,62 +128,69 @@ def solvent_protocol_dag(benzene_system): ) -def test_unit_tagging(solvent_protocol_dag, tmpdir): - # test that executing the Units includes correct generation and repeat info - dag_units = solvent_protocol_dag.protocol_units - with mock.patch( - "openfe_gromacs.protocols.gromacs_md.md_methods.GromacsMDSetupUnit.run", - return_value={ - "system_gro": "system.gro", - "system_top": "system.top", - "mdp_files": ["em.mdp", "nvt.mdp", "npt.mdp"], - }, - ): - results = [] - for u in dag_units: - ret = u.execute(context=gufe.Context(tmpdir, tmpdir)) - results.append(ret) - - repeats = set() - for ret in results: - assert isinstance(ret, gufe.ProtocolUnitResult) - assert ret.outputs["generation"] == 0 - repeats.add(ret.outputs["repeat_id"]) - # repeats are random ints, so check we got 2 individual numbers - assert len(repeats) == 2 - - -def test_gather(solvent_protocol_dag, tmpdir): - # check .gather behaves as expected - with mock.patch( - "openfe_gromacs.protocols.gromacs_md.md_methods.GromacsMDSetupUnit.run", - return_value={ - "system_gro": "system.gro", - "system_top": "system.top", - "mdp_files": ["em.mdp", "nvt.mdp", "npt.mdp"], - }, - ): - dagres = gufe.protocols.execute_DAG( - solvent_protocol_dag, - shared_basedir=tmpdir, - scratch_basedir=tmpdir, - keep_shared=True, - ) - - settings = GromacsMDProtocol.default_settings() - settings.protocol_repeats = 2 - prot = GromacsMDProtocol(settings=settings) - - res = prot.gather([dagres]) - - assert isinstance(res, GromacsMDProtocolResult) - - +# def test_unit_tagging(solvent_protocol_dag, tmpdir): +# # test that executing the Units includes correct generation and repeat info +# dag_units = solvent_protocol_dag.protocol_units +# print(dag_units) +# with mock.patch( +# "openfe_gromacs.protocols.gromacs_md.md_methods.GromacsMDSetupUnit.run", +# return_value={ +# "system_gro": "system.gro", +# "system_top": "system.top", +# "mdp_files": ["em.mdp", "nvt.mdp", "npt.mdp"], +# }, +# ): +# results = [] +# for u in dag_units: +# ret = u.execute(context=gufe.Context(tmpdir, tmpdir)) +# results.append(ret) +# print(results) +# repeats = set() +# for ret in results: +# print(ret) +# assert isinstance(ret, gufe.ProtocolUnitResult) +# assert ret.outputs["generation"] == 0 +# repeats.add(ret.outputs["repeat_id"]) +# # repeats are random ints, so check we got 2 individual numbers +# assert len(repeats) == 2 +# +# +# def test_gather(solvent_protocol_dag, tmpdir): +# # check .gather behaves as expected +# with mock.patch( +# "openfe_gromacs.protocols.gromacs_md.md_methods.GromacsMDSetupUnit.run", +# return_value={ +# "system_gro": "system.gro", +# "system_top": "system.top", +# "mdp_files": ["em.mdp", "nvt.mdp", "npt.mdp"], +# }, +# ): +# dagres = gufe.protocols.execute_DAG( +# solvent_protocol_dag, +# shared_basedir=tmpdir, +# scratch_basedir=tmpdir, +# keep_shared=True, +# ) +# +# settings = GromacsMDProtocol.default_settings() +# settings.protocol_repeats = 2 +# prot = GromacsMDProtocol(settings=settings) +# +# res = prot.gather([dagres]) +# +# assert isinstance(res, GromacsMDProtocolResult) +# +# def test_dry_run_ffcache_none(benzene_system, monkeypatch, tmpdir): monkeypatch.setenv("INTERCHANGE_EXPERIMENTAL", "1") settings = GromacsMDProtocol.default_settings() settings.output_settings_em.forcefield_cache = None - + settings.simulation_settings_em.nsteps = 10 + settings.simulation_settings_nvt.nsteps = 10 + settings.simulation_settings_npt.nsteps = 10 + settings.simulation_settings_em.rcoulomb = 1.0 * off_unit.nanometer + settings.simulation_settings_nvt.rcoulomb = 1.0 * off_unit.nanometer + settings.simulation_settings_npt.rcoulomb = 1.0 * off_unit.nanometer protocol = GromacsMDProtocol( settings=settings, ) @@ -207,7 +214,12 @@ def test_dry_many_molecules_solvent(benzene_many_solv_system, monkeypatch, tmpdi """ monkeypatch.setenv("INTERCHANGE_EXPERIMENTAL", "1") settings = GromacsMDProtocol.default_settings() - + settings.simulation_settings_em.nsteps = 10 + settings.simulation_settings_nvt.nsteps = 10 + settings.simulation_settings_npt.nsteps = 10 + settings.simulation_settings_em.rcoulomb = 1.0 * off_unit.nanometer + settings.simulation_settings_nvt.rcoulomb = 1.0 * off_unit.nanometer + settings.simulation_settings_npt.rcoulomb = 1.0 * off_unit.nanometer protocol = GromacsMDProtocol( settings=settings, ) @@ -218,53 +230,63 @@ def test_dry_many_molecules_solvent(benzene_many_solv_system, monkeypatch, tmpdi stateB=benzene_many_solv_system, mapping=None, ) - unit = list(dag.protocol_units)[0] + print(dag.protocol_units) + setup_unit = list(dag.protocol_units)[0] + run_unit = list(dag.protocol_units)[1] with tmpdir.as_cwd(): - system = unit.run(dry=True) - - -class TestProtocolResult: - @pytest.fixture() - def protocolresult(self, md_json): - d = json.loads(md_json, cls=gufe.tokenization.JSON_HANDLER.decoder) - - pr = openfe_gromacs.ProtocolResult.from_dict(d["protocol_result"]) - - return pr - - def test_reload_protocol_result(self, md_json): - d = json.loads(md_json, cls=gufe.tokenization.JSON_HANDLER.decoder) - - pr = GromacsMDProtocolResult.from_dict(d["protocol_result"]) - - assert pr - - def test_get_estimate(self, protocolresult): - est = protocolresult.get_estimate() - - assert est is None - - def test_get_uncertainty(self, protocolresult): - est = protocolresult.get_uncertainty() - - assert est is None - - def test_get_gro_filename(self, protocolresult): - gro = protocolresult.get_gro_filename() - - assert isinstance(gro, list) - assert isinstance(gro[0], pathlib.Path) - - def test_get_top_filename(self, protocolresult): - top = protocolresult.get_top_filename() - - assert isinstance(top, list) - assert isinstance(top[0], pathlib.Path) - - def test_get_mdp_filenames(self, protocolresult): - mdps = protocolresult.get_mdp_filenames() - - assert isinstance(mdps, list) - assert isinstance(mdps[0], list) - assert isinstance(mdps[0][0], pathlib.Path) + gufe.protocols.execute_DAG( + dag, + shared_basedir=tmpdir, + scratch_basedir=tmpdir, + keep_shared=False, + n_retries=3 + ) + # system = setup_unit.run(dry=True) + # system_run = run_unit.execute() + + +# class TestProtocolResult: +# @pytest.fixture() +# def protocolresult(self, md_json): +# d = json.loads(md_json, cls=gufe.tokenization.JSON_HANDLER.decoder) +# +# pr = openfe_gromacs.ProtocolResult.from_dict(d["protocol_result"]) +# +# return pr +# +# def test_reload_protocol_result(self, md_json): +# d = json.loads(md_json, cls=gufe.tokenization.JSON_HANDLER.decoder) +# +# pr = GromacsMDProtocolResult.from_dict(d["protocol_result"]) +# +# assert pr +# +# def test_get_estimate(self, protocolresult): +# est = protocolresult.get_estimate() +# +# assert est is None +# +# def test_get_uncertainty(self, protocolresult): +# est = protocolresult.get_uncertainty() +# +# assert est is None +# +# def test_get_gro_filename(self, protocolresult): +# gro = protocolresult.get_gro_filename() +# +# assert isinstance(gro, list) +# assert isinstance(gro[0], pathlib.Path) +# +# def test_get_top_filename(self, protocolresult): +# top = protocolresult.get_top_filename() +# +# assert isinstance(top, list) +# assert isinstance(top[0], pathlib.Path) +# +# def test_get_mdp_filenames(self, protocolresult): +# mdps = protocolresult.get_mdp_filenames() +# +# assert isinstance(mdps, list) +# assert isinstance(mdps[0], list) +# assert isinstance(mdps[0][0], pathlib.Path) From c83498d374d4afa0543f4e6b2becd626f98d0381 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 12:35:12 +0000 Subject: [PATCH 10/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- openfe_gromacs/tests/protocols/test_gromacs_md.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openfe_gromacs/tests/protocols/test_gromacs_md.py b/openfe_gromacs/tests/protocols/test_gromacs_md.py index 3878b12..9fb8a12 100644 --- a/openfe_gromacs/tests/protocols/test_gromacs_md.py +++ b/openfe_gromacs/tests/protocols/test_gromacs_md.py @@ -3,9 +3,10 @@ import json import pathlib from unittest import mock -from openff.units import unit as off_unit + import gufe import pytest +from openff.units import unit as off_unit import openfe_gromacs from openfe_gromacs.protocols.gromacs_md.md_methods import ( @@ -240,7 +241,7 @@ def test_dry_many_molecules_solvent(benzene_many_solv_system, monkeypatch, tmpdi shared_basedir=tmpdir, scratch_basedir=tmpdir, keep_shared=False, - n_retries=3 + n_retries=3, ) # system = setup_unit.run(dry=True) # system_run = run_unit.execute() From 9f8e20dc2f7eb145e46c7434bb000fa69b6a36b4 Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Mon, 5 Aug 2024 15:29:33 +0200 Subject: [PATCH 11/32] Add more outputs and update tests --- .../protocols/gromacs_md/md_methods.py | 129 +++++++++- .../tests/data/MDProtocol_json_results.gz | Bin 2951 -> 3641 bytes .../tests/protocols/test_gromacs_md.py | 239 +++++++++--------- 3 files changed, 252 insertions(+), 116 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index dcfe9fa..3a88576 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -175,7 +175,8 @@ def get_gro_filename(self) -> list[pathlib.Path]: traj : list[pathlib.Path] list of paths (pathlib.Path) to the simulation trajectory """ - gro = [pus[0].outputs["system_gro"] for pus in self.data.values()] + gro = [pus[0].outputs["system_gro"] for pus in self.data.values() if + 'GromacsMDSetupUnit' in pus[0].source_key] return gro @@ -188,7 +189,8 @@ def get_top_filename(self) -> list[pathlib.Path]: traj : list[pathlib.Path] list of paths (pathlib.Path) to the simulation trajectory """ - top = [pus[0].outputs["system_top"] for pus in self.data.values()] + top = [pus[0].outputs["system_top"] for pus in self.data.values() if + 'GromacsMDSetupUnit' in pus[0].source_key] return top @@ -202,10 +204,131 @@ def get_mdp_filenames(self) -> list[list[pathlib.Path]]: list of paths (pathlib.Path) to the mdp files for energy minimization, NVT and NPT MD runs """ - mdps = [pus[0].outputs["mdp_files"] for pus in self.data.values()] + mdps = [pus[0].outputs["mdp_files"] for pus in self.data.values() if + 'GromacsMDSetupUnit' in pus[0].source_key] return mdps + def get_gro_em_filename(self) -> list[pathlib.Path]: + """ + Get a list of paths to the .gro file, last frame of the + energy minimization + + Returns + ------- + gro : list[pathlib.Path] + list of paths (pathlib.Path) to the output .gro file + """ + gro = [pus[0].outputs["gro_em"] for pus in self.data.values() if + 'GromacsMDRunUnit' in pus[0].source_key] + + return gro + + def get_gro_em_filename(self) -> list[pathlib.Path]: + """ + Get a list of paths to the .gro file, last frame of the + energy minimization + + Returns + ------- + gro : list[pathlib.Path] + list of paths (pathlib.Path) to the output .gro file + """ + gro = [pus[0].outputs["gro_em"] for pus in self.data.values() if + 'GromacsMDRunUnit' in pus[0].source_key] + + return gro + + def get_tpr_em_filename(self) -> list[pathlib.Path]: + """ + Get a list of paths to the .tpr file of the + energy minimization + + Returns + ------- + tpr : list[pathlib.Path] + list of paths (pathlib.Path) to the output .tpr file + """ + file_path = [pus[0].outputs["tpr_em"] for pus in self.data.values() if + 'GromacsMDRunUnit' in pus[0].source_key] + + return file_path + + def get_trr_em_filename(self) -> list[pathlib.Path]: + """ + Get a list of paths to the .trr file of the + energy minimization + + Returns + ------- + file_path : list[pathlib.Path] + list of paths (pathlib.Path) to the output .trr file + """ + file_path = [pus[0].outputs["trr_em"] for pus in self.data.values() if + 'GromacsMDRunUnit' in pus[0].source_key] + + return file_path + + def get_xtc_em_filename(self) -> list[pathlib.Path]: + """ + Get a list of paths to the .xtc file of the + energy minimization + + Returns + ------- + file_path : list[pathlib.Path] + list of paths (pathlib.Path) to the output .xtc file + """ + file_path = [pus[0].outputs["xtc_em"] for pus in self.data.values() if + 'GromacsMDRunUnit' in pus[0].source_key] + + return file_path + + def get_edr_em_filename(self) -> list[pathlib.Path]: + """ + Get a list of paths to the .edr file of the + energy minimization + + Returns + ------- + file_path : list[pathlib.Path] + list of paths (pathlib.Path) to the output .edr file + """ + file_path = [pus[0].outputs["edr_em"] for pus in self.data.values() if + 'GromacsMDRunUnit' in pus[0].source_key] + + return file_path + + def get_log_em_filename(self) -> list[pathlib.Path]: + """ + Get a list of paths to the .log file of the + energy minimization + + Returns + ------- + file_path : list[pathlib.Path] + list of paths (pathlib.Path) to the output .log file + """ + file_path = [pus[0].outputs["log_em"] for pus in self.data.values() if + 'GromacsMDRunUnit' in pus[0].source_key] + + return file_path + + def get_cpt_em_filename(self) -> list[pathlib.Path]: + """ + Get a list of paths to the .cpt file of the + energy minimization + + Returns + ------- + file_path : list[pathlib.Path] + list of paths (pathlib.Path) to the output .cpt file + """ + file_path = [pus[0].outputs["cpt_em"] for pus in self.data.values() if + 'GromacsMDRunUnit' in pus[0].source_key] + + return file_path + class GromacsMDProtocol(gufe.Protocol): """ diff --git a/openfe_gromacs/tests/data/MDProtocol_json_results.gz b/openfe_gromacs/tests/data/MDProtocol_json_results.gz index b3064633c52fe828f36748d105d8eaeff0219a88..3a98e66a28e6a58c3aeae6442dadcd113ace816c 100644 GIT binary patch literal 3641 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 literal 2951 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 diff --git a/openfe_gromacs/tests/protocols/test_gromacs_md.py b/openfe_gromacs/tests/protocols/test_gromacs_md.py index 9fb8a12..22767a9 100644 --- a/openfe_gromacs/tests/protocols/test_gromacs_md.py +++ b/openfe_gromacs/tests/protocols/test_gromacs_md.py @@ -129,66 +129,39 @@ def solvent_protocol_dag(benzene_system): ) -# def test_unit_tagging(solvent_protocol_dag, tmpdir): -# # test that executing the Units includes correct generation and repeat info -# dag_units = solvent_protocol_dag.protocol_units -# print(dag_units) -# with mock.patch( -# "openfe_gromacs.protocols.gromacs_md.md_methods.GromacsMDSetupUnit.run", -# return_value={ -# "system_gro": "system.gro", -# "system_top": "system.top", -# "mdp_files": ["em.mdp", "nvt.mdp", "npt.mdp"], -# }, -# ): -# results = [] -# for u in dag_units: -# ret = u.execute(context=gufe.Context(tmpdir, tmpdir)) -# results.append(ret) -# print(results) -# repeats = set() -# for ret in results: -# print(ret) -# assert isinstance(ret, gufe.ProtocolUnitResult) -# assert ret.outputs["generation"] == 0 -# repeats.add(ret.outputs["repeat_id"]) -# # repeats are random ints, so check we got 2 individual numbers -# assert len(repeats) == 2 -# -# -# def test_gather(solvent_protocol_dag, tmpdir): -# # check .gather behaves as expected -# with mock.patch( -# "openfe_gromacs.protocols.gromacs_md.md_methods.GromacsMDSetupUnit.run", -# return_value={ -# "system_gro": "system.gro", -# "system_top": "system.top", -# "mdp_files": ["em.mdp", "nvt.mdp", "npt.mdp"], -# }, -# ): -# dagres = gufe.protocols.execute_DAG( -# solvent_protocol_dag, -# shared_basedir=tmpdir, -# scratch_basedir=tmpdir, -# keep_shared=True, -# ) -# -# settings = GromacsMDProtocol.default_settings() -# settings.protocol_repeats = 2 -# prot = GromacsMDProtocol(settings=settings) -# -# res = prot.gather([dagres]) -# -# assert isinstance(res, GromacsMDProtocolResult) -# -# +def test_unit_tagging_setup_unit(solvent_protocol_dag, tmpdir): + # test that executing the Units includes correct generation and repeat info + dag_units = solvent_protocol_dag.protocol_units + with mock.patch( + "openfe_gromacs.protocols.gromacs_md.md_methods.GromacsMDSetupUnit.run", + return_value={ + "system_gro": "system.gro", + "system_top": "system.top", + "mdp_files": ["em.mdp", "nvt.mdp", "npt.mdp"], + }, + ): + results = [] + for u in dag_units: + if type(u) is GromacsMDSetupUnit: + ret = u.execute(context=gufe.Context(tmpdir, tmpdir)) + results.append(ret) + repeats = set() + for ret in results: + assert isinstance(ret, gufe.ProtocolUnitResult) + assert ret.outputs["generation"] == 0 + repeats.add(ret.outputs["repeat_id"]) + # repeats are random ints, so check we got 1 individual number + # (there's only one Setup Unit, even with two repeats) + assert len(repeats) == 1 + + def test_dry_run_ffcache_none(benzene_system, monkeypatch, tmpdir): monkeypatch.setenv("INTERCHANGE_EXPERIMENTAL", "1") settings = GromacsMDProtocol.default_settings() settings.output_settings_em.forcefield_cache = None settings.simulation_settings_em.nsteps = 10 settings.simulation_settings_nvt.nsteps = 10 - settings.simulation_settings_npt.nsteps = 10 + settings.simulation_settings_npt.nsteps = 1 settings.simulation_settings_em.rcoulomb = 1.0 * off_unit.nanometer settings.simulation_settings_nvt.rcoulomb = 1.0 * off_unit.nanometer settings.simulation_settings_npt.rcoulomb = 1.0 * off_unit.nanometer @@ -203,10 +176,14 @@ def test_dry_run_ffcache_none(benzene_system, monkeypatch, tmpdir): stateB=benzene_system, mapping=None, ) - dag_unit = list(dag.protocol_units)[0] - with tmpdir.as_cwd(): - dag_unit.run(dry=True) + gufe.protocols.execute_DAG( + dag, + shared_basedir=tmpdir, + scratch_basedir=tmpdir, + keep_shared=False, + n_retries=3, + ) def test_dry_many_molecules_solvent(benzene_many_solv_system, monkeypatch, tmpdir): @@ -215,12 +192,11 @@ def test_dry_many_molecules_solvent(benzene_many_solv_system, monkeypatch, tmpdi """ monkeypatch.setenv("INTERCHANGE_EXPERIMENTAL", "1") settings = GromacsMDProtocol.default_settings() - settings.simulation_settings_em.nsteps = 10 - settings.simulation_settings_nvt.nsteps = 10 - settings.simulation_settings_npt.nsteps = 10 + # Only run an EM, no MD, to make the test faster + settings.simulation_settings_em.nsteps = 1 + settings.simulation_settings_nvt.nsteps = 0 + settings.simulation_settings_npt.nsteps = 0 settings.simulation_settings_em.rcoulomb = 1.0 * off_unit.nanometer - settings.simulation_settings_nvt.rcoulomb = 1.0 * off_unit.nanometer - settings.simulation_settings_npt.rcoulomb = 1.0 * off_unit.nanometer protocol = GromacsMDProtocol( settings=settings, ) @@ -231,9 +207,6 @@ def test_dry_many_molecules_solvent(benzene_many_solv_system, monkeypatch, tmpdi stateB=benzene_many_solv_system, mapping=None, ) - print(dag.protocol_units) - setup_unit = list(dag.protocol_units)[0] - run_unit = list(dag.protocol_units)[1] with tmpdir.as_cwd(): gufe.protocols.execute_DAG( @@ -243,51 +216,91 @@ def test_dry_many_molecules_solvent(benzene_many_solv_system, monkeypatch, tmpdi keep_shared=False, n_retries=3, ) - # system = setup_unit.run(dry=True) - # system_run = run_unit.execute() - - -# class TestProtocolResult: -# @pytest.fixture() -# def protocolresult(self, md_json): -# d = json.loads(md_json, cls=gufe.tokenization.JSON_HANDLER.decoder) -# -# pr = openfe_gromacs.ProtocolResult.from_dict(d["protocol_result"]) -# -# return pr -# -# def test_reload_protocol_result(self, md_json): -# d = json.loads(md_json, cls=gufe.tokenization.JSON_HANDLER.decoder) -# -# pr = GromacsMDProtocolResult.from_dict(d["protocol_result"]) -# -# assert pr -# -# def test_get_estimate(self, protocolresult): -# est = protocolresult.get_estimate() -# -# assert est is None -# -# def test_get_uncertainty(self, protocolresult): -# est = protocolresult.get_uncertainty() -# -# assert est is None -# -# def test_get_gro_filename(self, protocolresult): -# gro = protocolresult.get_gro_filename() -# -# assert isinstance(gro, list) -# assert isinstance(gro[0], pathlib.Path) -# -# def test_get_top_filename(self, protocolresult): -# top = protocolresult.get_top_filename() -# -# assert isinstance(top, list) -# assert isinstance(top[0], pathlib.Path) -# -# def test_get_mdp_filenames(self, protocolresult): -# mdps = protocolresult.get_mdp_filenames() -# -# assert isinstance(mdps, list) -# assert isinstance(mdps[0], list) -# assert isinstance(mdps[0][0], pathlib.Path) + + +class TestProtocolResult: + @pytest.fixture() + def protocolresult(self, md_json): + d = json.loads(md_json, cls=gufe.tokenization.JSON_HANDLER.decoder) + + pr = openfe_gromacs.ProtocolResult.from_dict(d["protocol_result"]) + + return pr + + def test_reload_protocol_result(self, md_json): + d = json.loads(md_json, cls=gufe.tokenization.JSON_HANDLER.decoder) + + pr = GromacsMDProtocolResult.from_dict(d["protocol_result"]) + + assert pr + + def test_get_estimate(self, protocolresult): + est = protocolresult.get_estimate() + + assert est is None + + def test_get_uncertainty(self, protocolresult): + est = protocolresult.get_uncertainty() + + assert est is None + + def test_get_gro_filename(self, protocolresult): + gro = protocolresult.get_gro_filename() + + assert isinstance(gro, list) + assert isinstance(gro[0], pathlib.Path) + + def test_get_top_filename(self, protocolresult): + top = protocolresult.get_top_filename() + + assert isinstance(top, list) + assert isinstance(top[0], pathlib.Path) + + def test_get_mdp_filenames(self, protocolresult): + mdps = protocolresult.get_mdp_filenames() + + assert isinstance(mdps, list) + assert isinstance(mdps[0], list) + assert isinstance(mdps[0][0], pathlib.Path) + + def test_get_gro_em_filename(self, protocolresult): + file_path = protocolresult.get_gro_em_filename() + + assert isinstance(file_path, list) + assert isinstance(file_path[0], pathlib.Path) + + def test_get_tpr_em_filename(self, protocolresult): + file_path = protocolresult.get_tpr_em_filename() + + assert isinstance(file_path, list) + assert isinstance(file_path[0], pathlib.Path) + + def test_get_trr_em_filename(self, protocolresult): + file_path = protocolresult.get_trr_em_filename() + + assert isinstance(file_path, list) + assert isinstance(file_path[0], pathlib.Path) + + def test_get_xtc_em_filename(self, protocolresult): + file_path = protocolresult.get_xtc_em_filename() + + assert isinstance(file_path, list) + assert isinstance(file_path[0], pathlib.Path) + + def test_get_edr_em_filename(self, protocolresult): + file_path = protocolresult.get_edr_em_filename() + + assert isinstance(file_path, list) + assert isinstance(file_path[0], pathlib.Path) + + def test_get_log_em_filename(self, protocolresult): + file_path = protocolresult.get_log_em_filename() + + assert isinstance(file_path, list) + assert isinstance(file_path[0], pathlib.Path) + + def test_get_cpt_em_filename(self, protocolresult): + file_path = protocolresult.get_cpt_em_filename() + + assert isinstance(file_path, list) + assert isinstance(file_path[0], pathlib.Path) From e01cf9e87a191a8aac943ec4f28ac16a2e1ab466 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 13:31:21 +0000 Subject: [PATCH 12/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../protocols/gromacs_md/md_methods.py | 77 +++++++++++++------ 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index 3a88576..13e6741 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -175,8 +175,11 @@ def get_gro_filename(self) -> list[pathlib.Path]: traj : list[pathlib.Path] list of paths (pathlib.Path) to the simulation trajectory """ - gro = [pus[0].outputs["system_gro"] for pus in self.data.values() if - 'GromacsMDSetupUnit' in pus[0].source_key] + gro = [ + pus[0].outputs["system_gro"] + for pus in self.data.values() + if "GromacsMDSetupUnit" in pus[0].source_key + ] return gro @@ -189,8 +192,11 @@ def get_top_filename(self) -> list[pathlib.Path]: traj : list[pathlib.Path] list of paths (pathlib.Path) to the simulation trajectory """ - top = [pus[0].outputs["system_top"] for pus in self.data.values() if - 'GromacsMDSetupUnit' in pus[0].source_key] + top = [ + pus[0].outputs["system_top"] + for pus in self.data.values() + if "GromacsMDSetupUnit" in pus[0].source_key + ] return top @@ -204,8 +210,11 @@ def get_mdp_filenames(self) -> list[list[pathlib.Path]]: list of paths (pathlib.Path) to the mdp files for energy minimization, NVT and NPT MD runs """ - mdps = [pus[0].outputs["mdp_files"] for pus in self.data.values() if - 'GromacsMDSetupUnit' in pus[0].source_key] + mdps = [ + pus[0].outputs["mdp_files"] + for pus in self.data.values() + if "GromacsMDSetupUnit" in pus[0].source_key + ] return mdps @@ -219,8 +228,11 @@ def get_gro_em_filename(self) -> list[pathlib.Path]: gro : list[pathlib.Path] list of paths (pathlib.Path) to the output .gro file """ - gro = [pus[0].outputs["gro_em"] for pus in self.data.values() if - 'GromacsMDRunUnit' in pus[0].source_key] + gro = [ + pus[0].outputs["gro_em"] + for pus in self.data.values() + if "GromacsMDRunUnit" in pus[0].source_key + ] return gro @@ -234,8 +246,11 @@ def get_gro_em_filename(self) -> list[pathlib.Path]: gro : list[pathlib.Path] list of paths (pathlib.Path) to the output .gro file """ - gro = [pus[0].outputs["gro_em"] for pus in self.data.values() if - 'GromacsMDRunUnit' in pus[0].source_key] + gro = [ + pus[0].outputs["gro_em"] + for pus in self.data.values() + if "GromacsMDRunUnit" in pus[0].source_key + ] return gro @@ -249,8 +264,11 @@ def get_tpr_em_filename(self) -> list[pathlib.Path]: tpr : list[pathlib.Path] list of paths (pathlib.Path) to the output .tpr file """ - file_path = [pus[0].outputs["tpr_em"] for pus in self.data.values() if - 'GromacsMDRunUnit' in pus[0].source_key] + file_path = [ + pus[0].outputs["tpr_em"] + for pus in self.data.values() + if "GromacsMDRunUnit" in pus[0].source_key + ] return file_path @@ -264,8 +282,11 @@ def get_trr_em_filename(self) -> list[pathlib.Path]: file_path : list[pathlib.Path] list of paths (pathlib.Path) to the output .trr file """ - file_path = [pus[0].outputs["trr_em"] for pus in self.data.values() if - 'GromacsMDRunUnit' in pus[0].source_key] + file_path = [ + pus[0].outputs["trr_em"] + for pus in self.data.values() + if "GromacsMDRunUnit" in pus[0].source_key + ] return file_path @@ -279,8 +300,11 @@ def get_xtc_em_filename(self) -> list[pathlib.Path]: file_path : list[pathlib.Path] list of paths (pathlib.Path) to the output .xtc file """ - file_path = [pus[0].outputs["xtc_em"] for pus in self.data.values() if - 'GromacsMDRunUnit' in pus[0].source_key] + file_path = [ + pus[0].outputs["xtc_em"] + for pus in self.data.values() + if "GromacsMDRunUnit" in pus[0].source_key + ] return file_path @@ -294,8 +318,11 @@ def get_edr_em_filename(self) -> list[pathlib.Path]: file_path : list[pathlib.Path] list of paths (pathlib.Path) to the output .edr file """ - file_path = [pus[0].outputs["edr_em"] for pus in self.data.values() if - 'GromacsMDRunUnit' in pus[0].source_key] + file_path = [ + pus[0].outputs["edr_em"] + for pus in self.data.values() + if "GromacsMDRunUnit" in pus[0].source_key + ] return file_path @@ -309,8 +336,11 @@ def get_log_em_filename(self) -> list[pathlib.Path]: file_path : list[pathlib.Path] list of paths (pathlib.Path) to the output .log file """ - file_path = [pus[0].outputs["log_em"] for pus in self.data.values() if - 'GromacsMDRunUnit' in pus[0].source_key] + file_path = [ + pus[0].outputs["log_em"] + for pus in self.data.values() + if "GromacsMDRunUnit" in pus[0].source_key + ] return file_path @@ -324,8 +354,11 @@ def get_cpt_em_filename(self) -> list[pathlib.Path]: file_path : list[pathlib.Path] list of paths (pathlib.Path) to the output .cpt file """ - file_path = [pus[0].outputs["cpt_em"] for pus in self.data.values() if - 'GromacsMDRunUnit' in pus[0].source_key] + file_path = [ + pus[0].outputs["cpt_em"] + for pus in self.data.values() + if "GromacsMDRunUnit" in pus[0].source_key + ] return file_path From 8f0133e35a8c2f0f3a778604a0a72777ae024efc Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Mon, 12 Aug 2024 09:51:03 +0200 Subject: [PATCH 13/32] small test --- openfe_gromacs/protocols/gromacs_md/md_methods.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index 13e6741..74463e4 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -1023,7 +1023,7 @@ def _execute( ctx.shared, ) - # Run NPT + # Run NPT MD simulation if sim_settings_npt.nsteps > 0: if verbose: self.logger.info("Running an NPT MD simulation") From 0dce60e53eb3822d291b81bafd35298d39e4478a Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Fri, 20 Sep 2024 13:02:52 +0200 Subject: [PATCH 14/32] Fix style --- .../protocols/gromacs_md/md_methods.py | 33 +++++++------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index 4d073c1..09d4fcd 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -903,14 +903,10 @@ def _run_gromacs( [ "gmx", "grompp", - "-f", - mdp, - "-c", - in_gro, - "-p", - top, - "-o", - tpr, + "-f", mdp, + "-c", in_gro, + "-p", top, + "-o", tpr, ], stdin=subprocess.PIPE, ) @@ -920,20 +916,13 @@ def _run_gromacs( [ "gmx", "mdrun", - "-s", - tpr.name, - "-cpo", - cpt, - "-o", - trr, - "-x", - xtc, - "-c", - out_gro, - "-e", - edr, - "-g", - log, + "-s", tpr.name, + "-cpo", cpt, + "-o", trr, + "-x", xtc, + "-c", out_gro, + "-e", edr, + "-g", log, ], stdin=subprocess.PIPE, cwd=shared_basebath, From c5a85b5cc3091f8128dfcf782e39b42be90235f3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 11:03:48 +0000 Subject: [PATCH 15/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../protocols/gromacs_md/md_methods.py | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index 09d4fcd..4d073c1 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -903,10 +903,14 @@ def _run_gromacs( [ "gmx", "grompp", - "-f", mdp, - "-c", in_gro, - "-p", top, - "-o", tpr, + "-f", + mdp, + "-c", + in_gro, + "-p", + top, + "-o", + tpr, ], stdin=subprocess.PIPE, ) @@ -916,13 +920,20 @@ def _run_gromacs( [ "gmx", "mdrun", - "-s", tpr.name, - "-cpo", cpt, - "-o", trr, - "-x", xtc, - "-c", out_gro, - "-e", edr, - "-g", log, + "-s", + tpr.name, + "-cpo", + cpt, + "-o", + trr, + "-x", + xtc, + "-c", + out_gro, + "-e", + edr, + "-g", + log, ], stdin=subprocess.PIPE, cwd=shared_basebath, From 6f625124a82afe96aae655e1e3704f690c6bb97c Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Fri, 20 Sep 2024 13:04:51 +0200 Subject: [PATCH 16/32] Change function to staticmethod --- openfe_gromacs/protocols/gromacs_md/md_methods.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index 09d4fcd..9b4f0cf 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -882,8 +882,8 @@ class GromacsMDRunUnit(gufe.ProtocolUnit): in Gromacs. """ + @staticmethod def _run_gromacs( - self, mdp, in_gro, top, From 714d86e1ee275c0562bce510fb38d9a2b3fdf4e7 Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Fri, 20 Sep 2024 13:53:25 +0200 Subject: [PATCH 17/32] Add typing to _run function --- .../protocols/gromacs_md/md_methods.py | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index 04eac08..f9b8a7c 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -884,18 +884,37 @@ class GromacsMDRunUnit(gufe.ProtocolUnit): @staticmethod def _run_gromacs( - mdp, - in_gro, - top, - tpr, - out_gro, - xtc, - trr, - cpt, - log, - edr, - shared_basebath, + mdp: pathlib.Path, + in_gro: pathlib.Path, + top: pathlib.Path, + tpr: pathlib.Path, + out_gro: str, + xtc: str, + trr: str, + cpt: str, + log: str, + edr: str, + shared_basebath: pathlib.Path, ): + """ + Running Gromacs gmx grompp and gmx mdrun commands using subprocess. + + Parameters + ---------- + :param mdp: pathlib.Path + Path to the mdp file + :param in_gro: pathlib.Path + :param top: pathlib.Path + :param tpr: pathlib.Path + :param out_gro: str + :param xtc: str + :param trr: str + :param cpt: str + :param log: str + :param edr: str + :param shared_basebath: Pathlike, optional + Where to run the calculation, defaults to current working directory + """ assert os.path.exists(in_gro) assert os.path.exists(top) assert os.path.exists(mdp) From c9ee5128bfeb0330b688d2cab289234a100cc479 Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Fri, 20 Sep 2024 13:58:11 +0200 Subject: [PATCH 18/32] Remove duplicate function --- .../protocols/gromacs_md/md_methods.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index f9b8a7c..f6adb11 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -232,24 +232,6 @@ def get_gro_em_filename(self) -> list[pathlib.Path]: return gro - def get_gro_em_filename(self) -> list[pathlib.Path]: - """ - Get a list of paths to the .gro file, last frame of the - energy minimization - - Returns - ------- - gro : list[pathlib.Path] - list of paths (pathlib.Path) to the output .gro file - """ - gro = [ - pus[0].outputs["gro_em"] - for pus in self.data.values() - if "GromacsMDRunUnit" in pus[0].source_key - ] - - return gro - def get_tpr_em_filename(self) -> list[pathlib.Path]: """ Get a list of paths to the .tpr file of the From e52a3d9a61ad0d8bbcd16efeb0504e50ce7b289e Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Fri, 20 Sep 2024 14:23:38 +0200 Subject: [PATCH 19/32] Output files together as dict --- .../protocols/gromacs_md/md_methods.py | 160 +++++++++++++----- .../tests/protocols/test_gromacs_md.py | 49 ++++-- 2 files changed, 154 insertions(+), 55 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index f6adb11..dfbca44 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -214,6 +214,38 @@ def get_mdp_filenames(self) -> list[list[pathlib.Path]]: return mdps + def get_filenames_em(self) -> dict[str, list[pathlib.Path]]: + """ + Get a list of paths to the files of the + energy minimization + Following file formats are stored in the dictionary under these keys: + - "gro_em" + - "tpr_em" + - "trr_em" + - "xtc_em" + - "edr_em" + - "log_em" + - "cpt_em" + + Returns + ------- + dict_em : dict[str, list[pathlib.Path]] + dictionary containing list of paths (pathlib.Path) + to the output files + """ + file_keys = ["gro_em", "tpr_em", "trr_em", "xtc_em", "edr_em", + "log_em", "cpt_em"] + dict_em = {} + for file in file_keys: + + file_path = [ + pus[0].outputs[file] + for pus in self.data.values() + if "GromacsMDRunUnit" in pus[0].source_key + ] + dict_em[file] = file_path + return dict_em + def get_gro_em_filename(self) -> list[pathlib.Path]: """ Get a list of paths to the .gro file, last frame of the @@ -232,46 +264,78 @@ def get_gro_em_filename(self) -> list[pathlib.Path]: return gro - def get_tpr_em_filename(self) -> list[pathlib.Path]: + def get_xtc_em_filename(self) -> list[pathlib.Path]: """ - Get a list of paths to the .tpr file of the + Get a list of paths to the .xtc file of the energy minimization Returns ------- - tpr : list[pathlib.Path] - list of paths (pathlib.Path) to the output .tpr file + file_path : list[pathlib.Path] + list of paths (pathlib.Path) to the output .xtc file """ file_path = [ - pus[0].outputs["tpr_em"] + pus[0].outputs["xtc_em"] for pus in self.data.values() if "GromacsMDRunUnit" in pus[0].source_key ] return file_path - def get_trr_em_filename(self) -> list[pathlib.Path]: + def get_filenames_nvt(self) -> dict[str, list[pathlib.Path]]: """ - Get a list of paths to the .trr file of the - energy minimization + Get a list of paths to the files of the + NVT equilibration + Following file formats are stored in the dictionary under these keys: + - "gro_nvt" + - "tpr_nvt" + - "trr_nvt" + - "xtc_nvt" + - "edr_nvt" + - "log_nvt" + - "cpt_nvt" Returns ------- - file_path : list[pathlib.Path] - list of paths (pathlib.Path) to the output .trr file + dict_nvt : dict[str, list[pathlib.Path]] + dictionary containing list of paths (pathlib.Path) + to the output files """ - file_path = [ - pus[0].outputs["trr_em"] + file_keys = ["gro_nvt", "tpr_nvt", "trr_nvt", "xtc_nvt", "edr_nvt", + "log_nvt", "cpt_nvt"] + dict_nvt = {} + for file in file_keys: + + file_path = [ + pus[0].outputs[file] + for pus in self.data.values() + if "GromacsMDRunUnit" in pus[0].source_key + ] + dict_nvt[file] = file_path + return dict_nvt + + def get_gro_nvt_filename(self) -> list[pathlib.Path]: + """ + Get a list of paths to the .gro file, last frame of the + NVT equilibration + + Returns + ------- + gro : list[pathlib.Path] + list of paths (pathlib.Path) to the output .gro file + """ + gro = [ + pus[0].outputs["gro_nvt"] for pus in self.data.values() if "GromacsMDRunUnit" in pus[0].source_key ] - return file_path + return gro - def get_xtc_em_filename(self) -> list[pathlib.Path]: + def get_xtc_nvt_filename(self) -> list[pathlib.Path]: """ Get a list of paths to the .xtc file of the - energy minimization + NVT equilibration Returns ------- @@ -279,61 +343,75 @@ def get_xtc_em_filename(self) -> list[pathlib.Path]: list of paths (pathlib.Path) to the output .xtc file """ file_path = [ - pus[0].outputs["xtc_em"] + pus[0].outputs["xtc_nvt"] for pus in self.data.values() if "GromacsMDRunUnit" in pus[0].source_key ] return file_path - def get_edr_em_filename(self) -> list[pathlib.Path]: + def get_filenames_npt(self) -> dict[str, list[pathlib.Path]]: """ - Get a list of paths to the .edr file of the - energy minimization + Get a list of paths to the files of the + NPT MD simulation + Following file formats are stored in the dictionary under these keys: + - "gro_npt" + - "tpr_npt" + - "trr_npt" + - "xtc_npt" + - "edr_npt" + - "log_npt" + - "cpt_npt" Returns ------- - file_path : list[pathlib.Path] - list of paths (pathlib.Path) to the output .edr file + dict_npt : dict[str, list[pathlib.Path]] + dictionary containing list of paths (pathlib.Path) + to the output files """ - file_path = [ - pus[0].outputs["edr_em"] - for pus in self.data.values() - if "GromacsMDRunUnit" in pus[0].source_key - ] - - return file_path + file_keys = ["gro_npt", "tpr_npt", "trr_npt", "xtc_npt", "edr_npt", + "log_npt", "cpt_npt"] + dict_npt = {} + for file in file_keys: + + file_path = [ + pus[0].outputs[file] + for pus in self.data.values() + if "GromacsMDRunUnit" in pus[0].source_key + ] + dict_npt[file] = file_path + return dict_npt - def get_log_em_filename(self) -> list[pathlib.Path]: + def get_gro_npt_filename(self) -> list[pathlib.Path]: """ - Get a list of paths to the .log file of the - energy minimization + Get a list of paths to the .gro file, last frame of the + NPT MD simulation Returns ------- - file_path : list[pathlib.Path] - list of paths (pathlib.Path) to the output .log file + gro : list[pathlib.Path] + list of paths (pathlib.Path) to the output .gro file """ - file_path = [ - pus[0].outputs["log_em"] + gro = [ + pus[0].outputs["gro_npt"] for pus in self.data.values() if "GromacsMDRunUnit" in pus[0].source_key ] - return file_path + return gro - def get_cpt_em_filename(self) -> list[pathlib.Path]: + def get_xtc_npt_filename(self) -> list[pathlib.Path]: """ - Get a list of paths to the .cpt file of the - energy minimization + Get a list of paths to the .xtc file of the + NPT MD simulation Returns ------- file_path : list[pathlib.Path] - list of paths (pathlib.Path) to the output .cpt file + list of paths (pathlib.Path) to the output .xtc file """ file_path = [ - pus[0].outputs["cpt_em"] + pus[0].outputs["xtc_npt"] for pus in self.data.values() if "GromacsMDRunUnit" in pus[0].source_key ] diff --git a/openfe_gromacs/tests/protocols/test_gromacs_md.py b/openfe_gromacs/tests/protocols/test_gromacs_md.py index 7a49be6..9ac6461 100644 --- a/openfe_gromacs/tests/protocols/test_gromacs_md.py +++ b/openfe_gromacs/tests/protocols/test_gromacs_md.py @@ -242,44 +242,65 @@ def test_get_mdp_filenames(self, protocolresult): assert isinstance(mdps[0], list) assert isinstance(mdps[0][0], pathlib.Path) + def test_get_filenames_em(self, protocolresult): + dict_file_path = protocolresult.get_filenames_em() + + assert isinstance(dict_file_path, dict) + for name, file_path in dict_file_path.items(): + assert isinstance(file_path, list) + assert len(file_path) == 7 + assert isinstance(file_path[0], pathlib.Path) + def test_get_gro_em_filename(self, protocolresult): file_path = protocolresult.get_gro_em_filename() assert isinstance(file_path, list) assert isinstance(file_path[0], pathlib.Path) - def test_get_tpr_em_filename(self, protocolresult): - file_path = protocolresult.get_tpr_em_filename() + def test_get_xtc_em_filename(self, protocolresult): + file_path = protocolresult.get_xtc_em_filename() assert isinstance(file_path, list) assert isinstance(file_path[0], pathlib.Path) - def test_get_trr_em_filename(self, protocolresult): - file_path = protocolresult.get_trr_em_filename() + def test_get_filenames_nvt(self, protocolresult): + dict_file_path = protocolresult.get_filenames_nvt() - assert isinstance(file_path, list) - assert isinstance(file_path[0], pathlib.Path) + assert isinstance(dict_file_path, dict) + for name, file_path in dict_file_path.items(): + assert isinstance(file_path, list) + assert len(file_path) == 7 + assert isinstance(file_path[0], pathlib.Path) - def test_get_xtc_em_filename(self, protocolresult): - file_path = protocolresult.get_xtc_em_filename() + def test_get_gro_nvt_filename(self, protocolresult): + file_path = protocolresult.get_gro_nvt_filename() assert isinstance(file_path, list) assert isinstance(file_path[0], pathlib.Path) - def test_get_edr_em_filename(self, protocolresult): - file_path = protocolresult.get_edr_em_filename() + def test_get_xtc_nvt_filename(self, protocolresult): + file_path = protocolresult.get_xtc_nvt_filename() assert isinstance(file_path, list) assert isinstance(file_path[0], pathlib.Path) - def test_get_log_em_filename(self, protocolresult): - file_path = protocolresult.get_log_em_filename() + def test_get_filenames_npt(self, protocolresult): + dict_file_path = protocolresult.get_filenames_npt() + + assert isinstance(dict_file_path, dict) + for name, file_path in dict_file_path.items(): + assert isinstance(file_path, list) + assert len(file_path) == 7 + assert isinstance(file_path[0], pathlib.Path) + + def test_get_gro_npt_filename(self, protocolresult): + file_path = protocolresult.get_gro_npt_filename() assert isinstance(file_path, list) assert isinstance(file_path[0], pathlib.Path) - def test_get_cpt_em_filename(self, protocolresult): - file_path = protocolresult.get_cpt_em_filename() + def test_get_xtc_npt_filename(self, protocolresult): + file_path = protocolresult.get_xtc_npt_filename() assert isinstance(file_path, list) assert isinstance(file_path[0], pathlib.Path) From 11cbd1392803432c66dd8208678e89fb48ec6fa2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 12:26:15 +0000 Subject: [PATCH 20/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../protocols/gromacs_md/md_methods.py | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index dfbca44..e3d1fa6 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -233,8 +233,15 @@ def get_filenames_em(self) -> dict[str, list[pathlib.Path]]: dictionary containing list of paths (pathlib.Path) to the output files """ - file_keys = ["gro_em", "tpr_em", "trr_em", "xtc_em", "edr_em", - "log_em", "cpt_em"] + file_keys = [ + "gro_em", + "tpr_em", + "trr_em", + "xtc_em", + "edr_em", + "log_em", + "cpt_em", + ] dict_em = {} for file in file_keys: @@ -301,8 +308,15 @@ def get_filenames_nvt(self) -> dict[str, list[pathlib.Path]]: dictionary containing list of paths (pathlib.Path) to the output files """ - file_keys = ["gro_nvt", "tpr_nvt", "trr_nvt", "xtc_nvt", "edr_nvt", - "log_nvt", "cpt_nvt"] + file_keys = [ + "gro_nvt", + "tpr_nvt", + "trr_nvt", + "xtc_nvt", + "edr_nvt", + "log_nvt", + "cpt_nvt", + ] dict_nvt = {} for file in file_keys: @@ -369,8 +383,15 @@ def get_filenames_npt(self) -> dict[str, list[pathlib.Path]]: dictionary containing list of paths (pathlib.Path) to the output files """ - file_keys = ["gro_npt", "tpr_npt", "trr_npt", "xtc_npt", "edr_npt", - "log_npt", "cpt_npt"] + file_keys = [ + "gro_npt", + "tpr_npt", + "trr_npt", + "xtc_npt", + "edr_npt", + "log_npt", + "cpt_npt", + ] dict_npt = {} for file in file_keys: From 68cc7f907b6843bb0db2bf5a7bcdf447fcaa91b6 Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Fri, 20 Sep 2024 16:07:28 +0200 Subject: [PATCH 21/32] Update tests run units --- .../protocols/gromacs_md/md_methods.py | 19 ++++--- .../tests/data/MDProtocol_json_results.gz | Bin 2914 -> 3641 bytes .../tests/protocols/test_gromacs_md.py | 51 +++++++++--------- .../tests/protocols/test_md_tokenization.py | 4 +- 4 files changed, 41 insertions(+), 33 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index e3d1fa6..e15da4b 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -72,13 +72,6 @@ "lj_pme_comb_rule": "Geometric", "ewald_geometry": "3d", "epsilon_surface": 0, - "nsttcouple": -1, - "tc_grps": "system", - "tau_t": 2.0 * unit.picosecond, - "pcoupltype": "isotropic", - "nstpcouple": -1, - "tau_p": 5 * unit.picosecond, - "compressibility": 4.5e-05 / unit.bar, "lincs_warnangle": 30 * unit.degree, "continuation": "no", "morse": "no", @@ -89,6 +82,16 @@ "emstep": 0.01 * unit.nanometer, } +PRE_DEFINED_SETTINGS_MD = { + "nsttcouple": -1, + "tc_grps": "system", + "tau_t": 2.0 * unit.picosecond, + "pcoupltype": "isotropic", + "nstpcouple": -1, + "tau_p": 5 * unit.picosecond, + "compressibility": 4.5e-05 / unit.bar, +} + def _dict2mdp(settings_dict: dict, shared_basepath): """ @@ -746,6 +749,7 @@ def _write_mdp_files(self, settings: dict, shared_basepath): settings["sim_settings_nvt"].dict() | settings["output_settings_nvt"].dict() | PRE_DEFINED_SETTINGS + | PRE_DEFINED_SETTINGS_MD ) mdp = _dict2mdp(settings_dict, shared_basepath) mdps.append(mdp) @@ -754,6 +758,7 @@ def _write_mdp_files(self, settings: dict, shared_basepath): settings["sim_settings_npt"].dict() | settings["output_settings_npt"].dict() | PRE_DEFINED_SETTINGS + | PRE_DEFINED_SETTINGS_MD ) mdp = _dict2mdp(settings_dict, shared_basepath) mdps.append(mdp) diff --git a/openfe_gromacs/tests/data/MDProtocol_json_results.gz b/openfe_gromacs/tests/data/MDProtocol_json_results.gz index dd4d32601325c5829c37b0a281f3a151dc714c6e..1371e5825e65c9fced123bd96c51cc41b9a4e327 100644 GIT binary patch literal 3641 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 MFNdMEsx&$P0O(k-&Hw-a diff --git a/openfe_gromacs/tests/protocols/test_gromacs_md.py b/openfe_gromacs/tests/protocols/test_gromacs_md.py index 9ac6461..fa60bda 100644 --- a/openfe_gromacs/tests/protocols/test_gromacs_md.py +++ b/openfe_gromacs/tests/protocols/test_gromacs_md.py @@ -134,7 +134,7 @@ def test_unit_tagging_setup_unit(solvent_protocol_dag, tmpdir): assert len(repeats) == 1 -def test_dry_run_ffcache_none(benzene_system, monkeypatch, tmpdir): +def test_dry_run_ffcache_none(benzene_system, monkeypatch, tmp_path_factory): monkeypatch.setenv("INTERCHANGE_EXPERIMENTAL", "1") settings = GromacsMDProtocol.default_settings() settings.output_settings_em.forcefield_cache = None @@ -155,17 +155,19 @@ def test_dry_run_ffcache_none(benzene_system, monkeypatch, tmpdir): stateB=benzene_system, mapping=None, ) - with tmpdir.as_cwd(): - gufe.protocols.execute_DAG( - dag, - shared_basedir=tmpdir, - scratch_basedir=tmpdir, - keep_shared=False, - n_retries=3, - ) + + shared_temp = tmp_path_factory.mktemp("shared") + scratch_temp = tmp_path_factory.mktemp("scratch") + gufe.protocols.execute_DAG( + dag, + shared_basedir=shared_temp, + scratch_basedir=scratch_temp, + keep_shared=False, + n_retries=3, + ) -def test_dry_many_molecules_solvent(benzene_many_solv_system, monkeypatch, tmpdir): +def test_dry_many_molecules_solvent(benzene_many_solv_system, monkeypatch, tmp_path_factory): """ A basic test flushing "will it work if you pass multiple molecules" """ @@ -187,14 +189,15 @@ def test_dry_many_molecules_solvent(benzene_many_solv_system, monkeypatch, tmpdi mapping=None, ) - with tmpdir.as_cwd(): - gufe.protocols.execute_DAG( - dag, - shared_basedir=tmpdir, - scratch_basedir=tmpdir, - keep_shared=False, - n_retries=3, - ) + shared_temp = tmp_path_factory.mktemp("shared") + scratch_temp = tmp_path_factory.mktemp("scratch") + gufe.protocols.execute_DAG( + dag, + shared_basedir=shared_temp, + scratch_basedir=scratch_temp, + keep_shared=False, + n_retries=3, + ) class TestProtocolResult: @@ -244,11 +247,11 @@ def test_get_mdp_filenames(self, protocolresult): def test_get_filenames_em(self, protocolresult): dict_file_path = protocolresult.get_filenames_em() - assert isinstance(dict_file_path, dict) + assert len(dict_file_path) == 7 for name, file_path in dict_file_path.items(): assert isinstance(file_path, list) - assert len(file_path) == 7 + assert len(file_path) == 1 assert isinstance(file_path[0], pathlib.Path) def test_get_gro_em_filename(self, protocolresult): @@ -265,11 +268,11 @@ def test_get_xtc_em_filename(self, protocolresult): def test_get_filenames_nvt(self, protocolresult): dict_file_path = protocolresult.get_filenames_nvt() - assert isinstance(dict_file_path, dict) + assert len(dict_file_path) == 7 for name, file_path in dict_file_path.items(): assert isinstance(file_path, list) - assert len(file_path) == 7 + assert len(file_path) == 1 assert isinstance(file_path[0], pathlib.Path) def test_get_gro_nvt_filename(self, protocolresult): @@ -286,11 +289,11 @@ def test_get_xtc_nvt_filename(self, protocolresult): def test_get_filenames_npt(self, protocolresult): dict_file_path = protocolresult.get_filenames_npt() - assert isinstance(dict_file_path, dict) + assert len(dict_file_path) == 7 for name, file_path in dict_file_path.items(): assert isinstance(file_path, list) - assert len(file_path) == 7 + assert len(file_path) == 1 assert isinstance(file_path[0], pathlib.Path) def test_get_gro_npt_filename(self, protocolresult): diff --git a/openfe_gromacs/tests/protocols/test_md_tokenization.py b/openfe_gromacs/tests/protocols/test_md_tokenization.py index 1e71aa3..a980fa3 100644 --- a/openfe_gromacs/tests/protocols/test_md_tokenization.py +++ b/openfe_gromacs/tests/protocols/test_md_tokenization.py @@ -41,7 +41,7 @@ def protocol_result(md_json): class TestGromacsMDProtocol(GufeTokenizableTestsMixin): cls = gromacs_md.GromacsMDProtocol - key = "GromacsMDProtocol-a32efc65b4df98bda778b1543fb34b70" + key = "GromacsMDProtocol-892e0d72a41b2087372deee4e8bc9a05" repr = f"<{key}>" @pytest.fixture() @@ -67,7 +67,7 @@ def test_key_stable(self): class TestGromacsMDProtocolResult(GufeTokenizableTestsMixin): cls = gromacs_md.GromacsMDProtocolResult - key = "GromacsMDProtocolResult-3e88fee8127fa7c04d8e5f1fa09d9c98" + key = "GromacsMDProtocolResult-f5a750033d57f5fd2177491cff9046c0" repr = f"<{key}>" @pytest.fixture() From c6a8137325758c8a4f5c0a968296b6a33f88189b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:08:20 +0000 Subject: [PATCH 22/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- openfe_gromacs/tests/protocols/test_gromacs_md.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openfe_gromacs/tests/protocols/test_gromacs_md.py b/openfe_gromacs/tests/protocols/test_gromacs_md.py index fa60bda..ac1608f 100644 --- a/openfe_gromacs/tests/protocols/test_gromacs_md.py +++ b/openfe_gromacs/tests/protocols/test_gromacs_md.py @@ -167,7 +167,9 @@ def test_dry_run_ffcache_none(benzene_system, monkeypatch, tmp_path_factory): ) -def test_dry_many_molecules_solvent(benzene_many_solv_system, monkeypatch, tmp_path_factory): +def test_dry_many_molecules_solvent( + benzene_many_solv_system, monkeypatch, tmp_path_factory +): """ A basic test flushing "will it work if you pass multiple molecules" """ From f60a8844d981234ed863b9d5a61830c1e830cba5 Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Fri, 20 Sep 2024 16:24:10 +0200 Subject: [PATCH 23/32] Update results file --- .../tests/data/MDProtocol_json_results.gz | Bin 3641 -> 3637 bytes .../tests/protocols/test_md_tokenization.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/openfe_gromacs/tests/data/MDProtocol_json_results.gz b/openfe_gromacs/tests/data/MDProtocol_json_results.gz index 1371e5825e65c9fced123bd96c51cc41b9a4e327..74844f98ea4e8dcadcff7263db6329c29b523b91 100644 GIT binary patch delta 3440 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 Q6|Qr!Guzg~)l5wP1n{cK3;+NC delta 3440 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 HuU-2$KYF=v diff --git a/openfe_gromacs/tests/protocols/test_md_tokenization.py b/openfe_gromacs/tests/protocols/test_md_tokenization.py index a980fa3..f21ca5d 100644 --- a/openfe_gromacs/tests/protocols/test_md_tokenization.py +++ b/openfe_gromacs/tests/protocols/test_md_tokenization.py @@ -41,7 +41,7 @@ def protocol_result(md_json): class TestGromacsMDProtocol(GufeTokenizableTestsMixin): cls = gromacs_md.GromacsMDProtocol - key = "GromacsMDProtocol-892e0d72a41b2087372deee4e8bc9a05" + key = "GromacsMDProtocol-13b24d4a018652722de10728b1a4efca" repr = f"<{key}>" @pytest.fixture() From df1f4b3d7065113887318fab6d5435df6706142e Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Fri, 20 Sep 2024 16:30:14 +0200 Subject: [PATCH 24/32] Small fix --- .../tests/data/MDProtocol_json_results.gz | Bin 3637 -> 3603 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/openfe_gromacs/tests/data/MDProtocol_json_results.gz b/openfe_gromacs/tests/data/MDProtocol_json_results.gz index 74844f98ea4e8dcadcff7263db6329c29b523b91..2f432bcce10c4b9a0fad83d564062b9461782318 100644 GIT binary patch literal 3603 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 a*=7HOh6g$CLBy`lluwIo7d&fk-1rBtB?+|v literal 3637 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 Uf$=T?*?D$3esSM?yq=2cAH-WAd;kCd From 9ead38a068b66ff3a3411019c4afb1314f7e247f Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Fri, 20 Sep 2024 16:37:06 +0200 Subject: [PATCH 25/32] Update tokenization test --- openfe_gromacs/tests/protocols/test_md_tokenization.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openfe_gromacs/tests/protocols/test_md_tokenization.py b/openfe_gromacs/tests/protocols/test_md_tokenization.py index f21ca5d..d5d1701 100644 --- a/openfe_gromacs/tests/protocols/test_md_tokenization.py +++ b/openfe_gromacs/tests/protocols/test_md_tokenization.py @@ -52,8 +52,7 @@ def instance(self, protocol): class TestMDSetupUnit(GufeTokenizableTestsMixin): cls = gromacs_md.GromacsMDSetupUnit repr = ( - "GromacsMDSetupUnit(Solvent MD SmallMoleculeComponent: " - "benzene repeat 0 generation 0)" + "GromacsMDSetupUnit(Solvent MD SmallMoleculeComponent: benzene)" ) key = None From b0236eac311cb041e1db4cfcb311840058760a76 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:37:20 +0000 Subject: [PATCH 26/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- openfe_gromacs/tests/protocols/test_md_tokenization.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openfe_gromacs/tests/protocols/test_md_tokenization.py b/openfe_gromacs/tests/protocols/test_md_tokenization.py index d5d1701..167bf0a 100644 --- a/openfe_gromacs/tests/protocols/test_md_tokenization.py +++ b/openfe_gromacs/tests/protocols/test_md_tokenization.py @@ -51,9 +51,7 @@ def instance(self, protocol): class TestMDSetupUnit(GufeTokenizableTestsMixin): cls = gromacs_md.GromacsMDSetupUnit - repr = ( - "GromacsMDSetupUnit(Solvent MD SmallMoleculeComponent: benzene)" - ) + repr = "GromacsMDSetupUnit(Solvent MD SmallMoleculeComponent: benzene)" key = None @pytest.fixture() From 557c453777baad238f0f50037bbe0f5238598739 Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Mon, 23 Sep 2024 10:06:35 +0200 Subject: [PATCH 27/32] Use .gro file from previous step --- .../protocols/gromacs_md/md_methods.py | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index e15da4b..b401935 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -1111,7 +1111,6 @@ def _execute( ] tpr = pathlib.Path(ctx.shared / output_settings_em.tpr_file) assert len(mdp) == 1 - # ToDo: If no traj should be written out, don't write empty file? self._run_gromacs( mdp[0], input_gro, @@ -1138,11 +1137,14 @@ def _execute( ] tpr = pathlib.Path(ctx.shared / output_settings_nvt.tpr_file) assert len(mdp) == 1 - # ToDo: Change .gro to output from EM if we do EM first, - # else original .gro file + # If EM was run, use the output from that to run NVT MD + if sim_settings_em.nsteps > 0: + gro = pathlib.Path(ctx.shared / output_settings_em.gro_file) + else: + gro = input_gro self._run_gromacs( mdp[0], - input_gro, + gro, input_top, tpr, output_settings_nvt.gro_file, @@ -1165,9 +1167,20 @@ def _execute( ] tpr = pathlib.Path(ctx.shared / output_settings_npt.tpr_file) assert len(mdp) == 1 + # If EM and/or NVT MD was run, use the output coordinate file + # from that to run NPT MD + if sim_settings_em.nsteps > 0: + if sim_settings_nvt.nsteps > 0: + gro = pathlib.Path( + ctx.shared / output_settings_nvt.gro_file) + else: + gro = pathlib.Path( + ctx.shared / output_settings_em.gro_file) + else: + gro = input_gro self._run_gromacs( mdp[0], - input_gro, + gro, input_top, tpr, output_settings_npt.gro_file, From 4c657bcca0a5fa62641dde946848f98feb5cecb8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:07:59 +0000 Subject: [PATCH 28/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- openfe_gromacs/protocols/gromacs_md/md_methods.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index b401935..d328f5d 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -1171,11 +1171,9 @@ def _execute( # from that to run NPT MD if sim_settings_em.nsteps > 0: if sim_settings_nvt.nsteps > 0: - gro = pathlib.Path( - ctx.shared / output_settings_nvt.gro_file) + gro = pathlib.Path(ctx.shared / output_settings_nvt.gro_file) else: - gro = pathlib.Path( - ctx.shared / output_settings_em.gro_file) + gro = pathlib.Path(ctx.shared / output_settings_em.gro_file) else: gro = input_gro self._run_gromacs( From fe82c07fa9e83202eb664291cb2391f856ba07d1 Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Mon, 23 Sep 2024 10:31:13 +0200 Subject: [PATCH 29/32] For now add ntomp to the SimulationSettings --- openfe_gromacs/protocols/gromacs_md/md_methods.py | 11 +++++++++-- openfe_gromacs/protocols/gromacs_md/md_settings.py | 6 ++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index d328f5d..5fc0567 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -113,6 +113,7 @@ def _dict2mdp(settings_dict: dict, shared_basepath): "edr_file", "log_file", "cpt_file", + "ntomp", ] for setting in non_mdps: settings_dict.pop(setting) @@ -980,6 +981,7 @@ def _run_gromacs( cpt: str, log: str, edr: str, + ntomp: int, shared_basebath: pathlib.Path, ): """ @@ -1039,6 +1041,10 @@ def _run_gromacs( edr, "-g", log, + "-ntmpi", + "1", + "-ntomp", + str(ntomp), ], stdin=subprocess.PIPE, cwd=shared_basebath, @@ -1082,8 +1088,6 @@ def _execute( else: shared_basepath = ctx.shared - # ToDo: Figure out how to specify the order in which to run things - # ToDo: Add output settings, e.g. name of output files protocol_settings: GromacsMDProtocolSettings = self._inputs["protocol"].settings sim_settings_em: EMSimulationSettings = protocol_settings.simulation_settings_em sim_settings_nvt: NVTSimulationSettings = ( @@ -1122,6 +1126,7 @@ def _execute( output_settings_em.cpt_file, output_settings_em.log_file, output_settings_em.edr_file, + sim_settings_em.ntomp, ctx.shared, ) @@ -1153,6 +1158,7 @@ def _execute( output_settings_nvt.cpt_file, output_settings_nvt.log_file, output_settings_nvt.edr_file, + sim_settings_nvt.ntomp, ctx.shared, ) @@ -1187,6 +1193,7 @@ def _execute( output_settings_npt.cpt_file, output_settings_npt.log_file, output_settings_npt.edr_file, + sim_settings_npt.ntomp, ctx.shared, ) diff --git a/openfe_gromacs/protocols/gromacs_md/md_settings.py b/openfe_gromacs/protocols/gromacs_md/md_settings.py index 36abfdf..d0f2e9c 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_settings.py +++ b/openfe_gromacs/protocols/gromacs_md/md_settings.py @@ -206,6 +206,12 @@ class Config: Number of iterations to correct for rotational lengthening in LINCS. Default 1. """ + ntomp: int = 1 + """ + Number of threads to be used for OpenMP multithreading. + GROMACS must be compiled with OpenMP support if a value greater than 1 is + set here. + """ @validator( "nsteps", From a16f4bdd9aee6d380b0debd8b6f70ce598ac8b9a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:32:55 +0000 Subject: [PATCH 30/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- openfe_gromacs/protocols/gromacs_md/md_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_settings.py b/openfe_gromacs/protocols/gromacs_md/md_settings.py index d0f2e9c..a77b1bd 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_settings.py +++ b/openfe_gromacs/protocols/gromacs_md/md_settings.py @@ -208,7 +208,7 @@ class Config: """ ntomp: int = 1 """ - Number of threads to be used for OpenMP multithreading. + Number of threads to be used for OpenMP multithreading. GROMACS must be compiled with OpenMP support if a value greater than 1 is set here. """ From f18541ab68974aecbdac7f17a84c5e72111e09f1 Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Mon, 23 Sep 2024 10:37:54 +0200 Subject: [PATCH 31/32] Small fix --- openfe_gromacs/protocols/gromacs_md/md_methods.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openfe_gromacs/protocols/gromacs_md/md_methods.py b/openfe_gromacs/protocols/gromacs_md/md_methods.py index 5fc0567..4dd114a 100644 --- a/openfe_gromacs/protocols/gromacs_md/md_methods.py +++ b/openfe_gromacs/protocols/gromacs_md/md_methods.py @@ -164,8 +164,6 @@ def get_uncertainty(self): return None - # TODO: Change this to return the actual outputs - def get_gro_filename(self) -> list[pathlib.Path]: """ Get a list of paths to the .gro file From 790cd2e5f2100b4f3157696fb9b7be4eda55a07b Mon Sep 17 00:00:00 2001 From: hannahbaumann Date: Mon, 23 Sep 2024 10:47:44 +0200 Subject: [PATCH 32/32] Update tokens --- openfe_gromacs/tests/protocols/test_md_tokenization.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfe_gromacs/tests/protocols/test_md_tokenization.py b/openfe_gromacs/tests/protocols/test_md_tokenization.py index 167bf0a..87c09a6 100644 --- a/openfe_gromacs/tests/protocols/test_md_tokenization.py +++ b/openfe_gromacs/tests/protocols/test_md_tokenization.py @@ -41,7 +41,7 @@ def protocol_result(md_json): class TestGromacsMDProtocol(GufeTokenizableTestsMixin): cls = gromacs_md.GromacsMDProtocol - key = "GromacsMDProtocol-13b24d4a018652722de10728b1a4efca" + key = "GromacsMDProtocol-76fa290de019030035f2010e9155f57f" repr = f"<{key}>" @pytest.fixture()