diff --git a/python/BioSimSpace/IO/_io.py b/python/BioSimSpace/IO/_io.py index c36696051..39369ca75 100644 --- a/python/BioSimSpace/IO/_io.py +++ b/python/BioSimSpace/IO/_io.py @@ -526,7 +526,9 @@ def readMolecules( return _System(system) -def saveMolecules(filebase, system, fileformat, property_map={}, **kwargs): +def saveMolecules( + filebase, system, fileformat, match_water=True, property_map={}, **kwargs +): """ Save a molecular system to file. @@ -544,6 +546,12 @@ def saveMolecules(filebase, system, fileformat, property_map={}, **kwargs): fileformat : str, [str] The file format (or formats) to save to. + match_water : bool + Whether to update the naming of water molecules to match the expected + convention for the chosen file format. This is useful when a system + is being saved to a different file format to that from which it was + loaded. + property_map : dict A dictionary that maps system "properties" to their user defined values. This allows the user to refer to properties @@ -633,6 +641,10 @@ def saveMolecules(filebase, system, fileformat, property_map={}, **kwargs): if not all(isinstance(x, str) for x in fileformat): raise TypeError("'fileformat' must be a 'str' or a 'list' of 'str' types.") + # Validate the match_water flag. + if not isinstance(match_water, bool): + raise TypeError("'match_water' must be of type 'bool'.") + # Make a list of the matched file formats. formats = [] @@ -714,14 +726,20 @@ def saveMolecules(filebase, system, fileformat, property_map={}, **kwargs): # and save GROMACS files with an extension such that they can be run # directly by GROMACS without needing to be renamed. if format.upper() == "PRM7": - system_copy = system.copy() - system_copy._set_water_topology("AMBER", _property_map) + if match_water: + system_copy = system.copy() + system_copy._set_water_topology("AMBER", _property_map) + else: + system_copy = system file = _SireIO.MoleculeParser.save( system_copy._sire_object, filebase, _property_map ) elif format.upper() == "GROTOP": - system_copy = system.copy() - system_copy._set_water_topology("GROMACS", _property_map) + if match_water: + system_copy = system.copy() + system_copy._set_water_topology("GROMACS", _property_map) + else: + system_copy = system file = _SireIO.MoleculeParser.save( system_copy._sire_object, filebase, _property_map )[0] @@ -729,12 +747,17 @@ def saveMolecules(filebase, system, fileformat, property_map={}, **kwargs): _os.rename(file, new_file) file = [new_file] elif format.upper() == "GRO87": + if match_water: + system_copy = system.copy() + system_copy._set_water_topology("GROMACS", _property_map) + else: + system_copy = system # Write to 3dp by default, unless greater precision is # requested by the user. if "precision" not in _property_map: _property_map["precision"] = _SireBase.wrap(3) file = _SireIO.MoleculeParser.save( - system._sire_object, filebase, _property_map + system_copy._sire_object, filebase, _property_map )[0] new_file = file.replace("gro87", "gro") _os.rename(file, new_file) diff --git a/python/BioSimSpace/Parameters/_Protocol/_amber.py b/python/BioSimSpace/Parameters/_Protocol/_amber.py index e4419cb29..d798ab5ca 100644 --- a/python/BioSimSpace/Parameters/_Protocol/_amber.py +++ b/python/BioSimSpace/Parameters/_Protocol/_amber.py @@ -410,7 +410,7 @@ def _run_tleap(self, molecule, work_dir): prefix + "leap", renumbered_molecule, "pdb", - self._property_map, + property_map=self._property_map, ) except Exception as e: raise @@ -557,7 +557,9 @@ def _run_pdb2gmx(self, molecule, work_dir): # Write the system to a PDB file. try: - _IO.saveMolecules(prefix + "leap", _molecule, "pdb", self._property_map) + _IO.saveMolecules( + prefix + "leap", _molecule, "pdb", property_map=self._property_map + ) except Exception as e: msg = "Failed to write system to 'PDB' format." if _isVerbose(): @@ -1016,7 +1018,7 @@ def run(self, molecule, work_dir=None, queue=None): # Write the system to a PDB file. try: _IO.saveMolecules( - prefix + "antechamber", new_mol, "pdb", self._property_map + prefix + "antechamber", new_mol, "pdb", property_map=self._property_map ) except Exception as e: msg = "Failed to write system to 'PDB' format." diff --git a/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py b/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py index de102daeb..8c160e320 100644 --- a/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py +++ b/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py @@ -213,7 +213,10 @@ def run(self, molecule, work_dir=None, queue=None): # Write the molecule to SDF format. try: _IO.saveMolecules( - prefix + "molecule", molecule, "sdf", self._property_map + prefix + "molecule", + molecule, + "sdf", + property_map=self._property_map, ) except Exception as e: msg = "Failed to write the molecule to 'SDF' format." @@ -229,7 +232,10 @@ def run(self, molecule, work_dir=None, queue=None): # Write the molecule to a PDB file. try: _IO.saveMolecules( - prefix + "molecule", molecule, "pdb", self._property_map + prefix + "molecule", + molecule, + "pdb", + property_map=self._property_map, ) except Exception as e: msg = "Failed to write the molecule to 'PDB' format." diff --git a/python/BioSimSpace/Process/_amber.py b/python/BioSimSpace/Process/_amber.py index e755cf16c..9a0679f40 100644 --- a/python/BioSimSpace/Process/_amber.py +++ b/python/BioSimSpace/Process/_amber.py @@ -212,7 +212,9 @@ def _setup(self): # PRM file (topology). try: file = _os.path.splitext(self._top_file)[0] - _IO.saveMolecules(file, system, "prm7", property_map=self._property_map) + _IO.saveMolecules( + file, system, "prm7", match_water=False, property_map=self._property_map + ) except Exception as e: msg = "Failed to write system to 'PRM7' format." if _isVerbose(): diff --git a/python/BioSimSpace/Process/_gromacs.py b/python/BioSimSpace/Process/_gromacs.py index 98626325a..7ae77339c 100644 --- a/python/BioSimSpace/Process/_gromacs.py +++ b/python/BioSimSpace/Process/_gromacs.py @@ -258,11 +258,15 @@ def _setup(self): # GRO87 file. file = _os.path.splitext(self._gro_file)[0] - _IO.saveMolecules(file, system, "gro87", property_map=self._property_map) + _IO.saveMolecules( + file, system, "gro87", match_water=False, property_map=self._property_map + ) # TOP file. file = _os.path.splitext(self._top_file)[0] - _IO.saveMolecules(file, system, "grotop", property_map=self._property_map) + _IO.saveMolecules( + file, system, "grotop", match_water=False, property_map=self._property_map + ) # Create the binary input file name. self._tpr_file = "%s/%s.tpr" % (self._work_dir, self._name) diff --git a/python/BioSimSpace/Process/_openmm.py b/python/BioSimSpace/Process/_openmm.py index fc0871637..b08070482 100644 --- a/python/BioSimSpace/Process/_openmm.py +++ b/python/BioSimSpace/Process/_openmm.py @@ -252,7 +252,9 @@ def _setup(self): # PRM file (topology). try: file = _os.path.splitext(self._top_file)[0] - _IO.saveMolecules(file, system, "prm7", property_map=self._property_map) + _IO.saveMolecules( + file, system, "prm7", match_water=False, property_map=self._property_map + ) except Exception as e: msg = "Failed to write system to 'PRM7' format." if _isVerbose(): diff --git a/python/BioSimSpace/Process/_somd.py b/python/BioSimSpace/Process/_somd.py index 27582b2e5..e785f5a78 100644 --- a/python/BioSimSpace/Process/_somd.py +++ b/python/BioSimSpace/Process/_somd.py @@ -357,7 +357,9 @@ def _setup(self): # PRM file (topology). try: - _IO.saveMolecules(file, system, "prm7", property_map=self._property_map) + _IO.saveMolecules( + file, system, "prm7", match_water=False, property_map=self._property_map + ) except Exception as e: msg = "Failed to write system to 'PRM7' format." if _isVerbose(): diff --git a/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py b/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py index c36696051..39369ca75 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py +++ b/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py @@ -526,7 +526,9 @@ def readMolecules( return _System(system) -def saveMolecules(filebase, system, fileformat, property_map={}, **kwargs): +def saveMolecules( + filebase, system, fileformat, match_water=True, property_map={}, **kwargs +): """ Save a molecular system to file. @@ -544,6 +546,12 @@ def saveMolecules(filebase, system, fileformat, property_map={}, **kwargs): fileformat : str, [str] The file format (or formats) to save to. + match_water : bool + Whether to update the naming of water molecules to match the expected + convention for the chosen file format. This is useful when a system + is being saved to a different file format to that from which it was + loaded. + property_map : dict A dictionary that maps system "properties" to their user defined values. This allows the user to refer to properties @@ -633,6 +641,10 @@ def saveMolecules(filebase, system, fileformat, property_map={}, **kwargs): if not all(isinstance(x, str) for x in fileformat): raise TypeError("'fileformat' must be a 'str' or a 'list' of 'str' types.") + # Validate the match_water flag. + if not isinstance(match_water, bool): + raise TypeError("'match_water' must be of type 'bool'.") + # Make a list of the matched file formats. formats = [] @@ -714,14 +726,20 @@ def saveMolecules(filebase, system, fileformat, property_map={}, **kwargs): # and save GROMACS files with an extension such that they can be run # directly by GROMACS without needing to be renamed. if format.upper() == "PRM7": - system_copy = system.copy() - system_copy._set_water_topology("AMBER", _property_map) + if match_water: + system_copy = system.copy() + system_copy._set_water_topology("AMBER", _property_map) + else: + system_copy = system file = _SireIO.MoleculeParser.save( system_copy._sire_object, filebase, _property_map ) elif format.upper() == "GROTOP": - system_copy = system.copy() - system_copy._set_water_topology("GROMACS", _property_map) + if match_water: + system_copy = system.copy() + system_copy._set_water_topology("GROMACS", _property_map) + else: + system_copy = system file = _SireIO.MoleculeParser.save( system_copy._sire_object, filebase, _property_map )[0] @@ -729,12 +747,17 @@ def saveMolecules(filebase, system, fileformat, property_map={}, **kwargs): _os.rename(file, new_file) file = [new_file] elif format.upper() == "GRO87": + if match_water: + system_copy = system.copy() + system_copy._set_water_topology("GROMACS", _property_map) + else: + system_copy = system # Write to 3dp by default, unless greater precision is # requested by the user. if "precision" not in _property_map: _property_map["precision"] = _SireBase.wrap(3) file = _SireIO.MoleculeParser.save( - system._sire_object, filebase, _property_map + system_copy._sire_object, filebase, _property_map )[0] new_file = file.replace("gro87", "gro") _os.rename(file, new_file) diff --git a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_amber.py b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_amber.py index e4419cb29..d798ab5ca 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_amber.py +++ b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_amber.py @@ -410,7 +410,7 @@ def _run_tleap(self, molecule, work_dir): prefix + "leap", renumbered_molecule, "pdb", - self._property_map, + property_map=self._property_map, ) except Exception as e: raise @@ -557,7 +557,9 @@ def _run_pdb2gmx(self, molecule, work_dir): # Write the system to a PDB file. try: - _IO.saveMolecules(prefix + "leap", _molecule, "pdb", self._property_map) + _IO.saveMolecules( + prefix + "leap", _molecule, "pdb", property_map=self._property_map + ) except Exception as e: msg = "Failed to write system to 'PDB' format." if _isVerbose(): @@ -1016,7 +1018,7 @@ def run(self, molecule, work_dir=None, queue=None): # Write the system to a PDB file. try: _IO.saveMolecules( - prefix + "antechamber", new_mol, "pdb", self._property_map + prefix + "antechamber", new_mol, "pdb", property_map=self._property_map ) except Exception as e: msg = "Failed to write system to 'PDB' format." diff --git a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py index de102daeb..8c160e320 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py +++ b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py @@ -213,7 +213,10 @@ def run(self, molecule, work_dir=None, queue=None): # Write the molecule to SDF format. try: _IO.saveMolecules( - prefix + "molecule", molecule, "sdf", self._property_map + prefix + "molecule", + molecule, + "sdf", + property_map=self._property_map, ) except Exception as e: msg = "Failed to write the molecule to 'SDF' format." @@ -229,7 +232,10 @@ def run(self, molecule, work_dir=None, queue=None): # Write the molecule to a PDB file. try: _IO.saveMolecules( - prefix + "molecule", molecule, "pdb", self._property_map + prefix + "molecule", + molecule, + "pdb", + property_map=self._property_map, ) except Exception as e: msg = "Failed to write the molecule to 'PDB' format." diff --git a/python/BioSimSpace/Sandpit/Exscientia/Process/_amber.py b/python/BioSimSpace/Sandpit/Exscientia/Process/_amber.py index 7595ff33f..367d346f2 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/Process/_amber.py +++ b/python/BioSimSpace/Sandpit/Exscientia/Process/_amber.py @@ -327,7 +327,13 @@ def _write_system(self, system, coord_file=None, topol_file=None, ref_file=None) if topol_file is not None: try: file = _os.path.splitext(topol_file)[0] - _IO.saveMolecules(file, system, "prm7", property_map=self._property_map) + _IO.saveMolecules( + file, + system, + "prm7", + match_waters=False, + property_map=self._property_map, + ) except Exception as e: msg = "Failed to write system to 'PRM7' format." if _isVerbose(): diff --git a/python/BioSimSpace/Sandpit/Exscientia/Process/_gromacs.py b/python/BioSimSpace/Sandpit/Exscientia/Process/_gromacs.py index a772e9090..ecac997d1 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/Process/_gromacs.py +++ b/python/BioSimSpace/Sandpit/Exscientia/Process/_gromacs.py @@ -347,17 +347,35 @@ def _write_system(self, system, coord_file=None, topol_file=None, ref_file=None) # GRO87 coordinate files. if coord_file is not None: file = _os.path.splitext(coord_file)[0] - _IO.saveMolecules(file, system, "gro87", property_map=self._property_map) + _IO.saveMolecules( + file, + system, + "gro87", + match_waters=False, + property_map=self._property_map, + ) # GRO87 reference files. if ref_file is not None: file = _os.path.splitext(ref_file)[0] - _IO.saveMolecules(file, system, "gro87", property_map=self._property_map) + _IO.saveMolecules( + file, + system, + "gro87", + match_waters=False, + property_map=self._property_map, + ) # TOP file. if topol_file is not None: file = _os.path.splitext(topol_file)[0] - _IO.saveMolecules(file, system, "grotop", property_map=self._property_map) + _IO.saveMolecules( + file, + system, + "grotop", + match_waters=False, + property_map=self._property_map, + ) # Write the restraint to the topology file if self._restraint: diff --git a/python/BioSimSpace/Sandpit/Exscientia/Process/_openmm.py b/python/BioSimSpace/Sandpit/Exscientia/Process/_openmm.py index 35b830b65..83e9d5f5a 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/Process/_openmm.py +++ b/python/BioSimSpace/Sandpit/Exscientia/Process/_openmm.py @@ -251,7 +251,13 @@ def _setup(self): # PRM file (topology). try: file = _os.path.splitext(self._top_file)[0] - _IO.saveMolecules(file, system, "prm7", property_map=self._property_map) + _IO.saveMolecules( + file, + system, + "prm7", + match_waters=False, + property_map=self._property_map, + ) except Exception as e: msg = "Failed to write system to 'PRM7' format." if _isVerbose(): diff --git a/python/BioSimSpace/Sandpit/Exscientia/Process/_somd.py b/python/BioSimSpace/Sandpit/Exscientia/Process/_somd.py index 97882c198..4a62ea2f6 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/Process/_somd.py +++ b/python/BioSimSpace/Sandpit/Exscientia/Process/_somd.py @@ -369,7 +369,13 @@ def _setup(self): # PRM file (topology). try: file = _os.path.splitext(self._top_file)[0] - _IO.saveMolecules(file, system, "prm7", property_map=self._property_map) + _IO.saveMolecules( + file, + system, + "prm7", + match_waters=False, + property_map=self._property_map, + ) except Exception as e: msg = "Failed to write system to 'PRM7' format." if _isVerbose(): diff --git a/python/BioSimSpace/Sandpit/Exscientia/Solvent/_solvent.py b/python/BioSimSpace/Sandpit/Exscientia/Solvent/_solvent.py index 7fa76eff4..bac6f9220 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/Solvent/_solvent.py +++ b/python/BioSimSpace/Sandpit/Exscientia/Solvent/_solvent.py @@ -954,7 +954,13 @@ def _solvate( # First, generate a box file corresponding to the requested geometry. if molecule is not None: # Write the molecule/system to a GRO files. - _IO.saveMolecules("input", molecule, "gro87", property_map=_property_map) + _IO.saveMolecules( + "input", + molecule, + "gro87", + match_waters=False, + property_map=_property_map, + ) # We need to create a dummy input file with no molecule in it. else: @@ -1122,10 +1128,18 @@ def _solvate( try: # Write the molecule + water system to file. _IO.saveMolecules( - "solvated", system, "gro87", property_map=_property_map + "solvated", + system, + "gro87", + match_waters=False, + property_map=_property_map, ) _IO.saveMolecules( - "solvated", system, "grotop", property_map=_property_map + "solvated", + system, + "grotop", + match_waters=False, + property_map=_property_map, ) except Exception as e: msg = ( diff --git a/python/BioSimSpace/Solvent/_solvent.py b/python/BioSimSpace/Solvent/_solvent.py index 7fa76eff4..bac6f9220 100644 --- a/python/BioSimSpace/Solvent/_solvent.py +++ b/python/BioSimSpace/Solvent/_solvent.py @@ -954,7 +954,13 @@ def _solvate( # First, generate a box file corresponding to the requested geometry. if molecule is not None: # Write the molecule/system to a GRO files. - _IO.saveMolecules("input", molecule, "gro87", property_map=_property_map) + _IO.saveMolecules( + "input", + molecule, + "gro87", + match_waters=False, + property_map=_property_map, + ) # We need to create a dummy input file with no molecule in it. else: @@ -1122,10 +1128,18 @@ def _solvate( try: # Write the molecule + water system to file. _IO.saveMolecules( - "solvated", system, "gro87", property_map=_property_map + "solvated", + system, + "gro87", + match_waters=False, + property_map=_property_map, ) _IO.saveMolecules( - "solvated", system, "grotop", property_map=_property_map + "solvated", + system, + "grotop", + match_waters=False, + property_map=_property_map, ) except Exception as e: msg = (