From c10d28b9aa56f501a8c0ade2628994237625b72c Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Fri, 22 Mar 2024 13:44:31 +0000 Subject: [PATCH 01/14] Remove redundant openff.Topology import. --- python/BioSimSpace/Parameters/_Protocol/_openforcefield.py | 2 -- .../Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py b/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py index 2f6358893..0367b79b0 100644 --- a/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py +++ b/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py @@ -76,12 +76,10 @@ if _have_imported(_openff): from openff.interchange import Interchange as _Interchange from openff.toolkit.topology import Molecule as _OpenFFMolecule - from openff.toolkit.topology import Topology as _OpenFFTopology from openff.toolkit.typing.engines.smirnoff import ForceField as _Forcefield else: _Interchange = _openff _OpenFFMolecule = _openff - _OpenFFTopology = _openff _Forcefield = _openff # Reset stderr. diff --git a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py index 2f6358893..0367b79b0 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py +++ b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py @@ -76,12 +76,10 @@ if _have_imported(_openff): from openff.interchange import Interchange as _Interchange from openff.toolkit.topology import Molecule as _OpenFFMolecule - from openff.toolkit.topology import Topology as _OpenFFTopology from openff.toolkit.typing.engines.smirnoff import ForceField as _Forcefield else: _Interchange = _openff _OpenFFMolecule = _openff - _OpenFFTopology = _openff _Forcefield = _openff # Reset stderr. From 40ecb824fafe7deeb64c5b3fb2c9e9103db7ff10 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Fri, 22 Mar 2024 14:03:23 +0000 Subject: [PATCH 02/14] Add support for using NAGL to generate AM1BCC charges. --- .../Parameters/_Protocol/_openforcefield.py | 42 ++++++++++++++++++- .../Parameters/_Protocol/_openforcefield.py | 42 ++++++++++++++++++- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py b/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py index 0367b79b0..5cb2d6c8e 100644 --- a/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py +++ b/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py @@ -77,6 +77,27 @@ from openff.interchange import Interchange as _Interchange from openff.toolkit.topology import Molecule as _OpenFFMolecule from openff.toolkit.typing.engines.smirnoff import ForceField as _Forcefield + + try: + from openff.toolkit.utils.nagl_wrapper import ( + NAGLToolkitWrapper as _NAGLToolkitWrapper, + ) + + _has_nagl = _NAGLToolkitWrapper.is_available() + from openff.nagl_models import get_models_by_type as _get_models_by_type + + _models = _get_models_by_type("am1bcc") + try: + # Find the most recent AM1-BCC release candidate. + _nagl = _NAGLToolkitWrapper() + _nagl_model = sorted( + [str(model) for model in _models if "rc" in str(model)], reverse=True + )[0] + except: + _has_nagl = False + del _models + except: + _has_nagl = False else: _Interchange = _openff _OpenFFMolecule = _openff @@ -289,6 +310,23 @@ def run(self, molecule, work_dir=None, queue=None): else: raise _ThirdPartyError(msg) from None + # Apply AM1-BCC charges using NAGL. + if _has_nagl: + try: + _nagl.assign_partial_charges( + off_molecule, partial_charge_method=_nagl_model + ) + except Exception as e: + msg = "Failed to assign AM1-BCC charges using NAGL." + if _isVerbose(): + msg += ": " + getattr(e, "message", repr(e)) + raise _ThirdPartyError(msg) from e + else: + raise _ThirdPartyError(msg) from None + charge_from_molecules = [off_molecule] + else: + charge_from_molecules = None + # Extract the molecular topology. try: off_topology = off_molecule.to_topology() @@ -315,7 +353,9 @@ def run(self, molecule, work_dir=None, queue=None): # Create an Interchange object. try: interchange = _Interchange.from_smirnoff( - force_field=forcefield, topology=off_topology + force_field=forcefield, + topology=off_topology, + charge_from_molecules=charge_from_molecules, ) except Exception as e: msg = "Unable to create OpenFF Interchange object!" diff --git a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py index 0367b79b0..5cb2d6c8e 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py +++ b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py @@ -77,6 +77,27 @@ from openff.interchange import Interchange as _Interchange from openff.toolkit.topology import Molecule as _OpenFFMolecule from openff.toolkit.typing.engines.smirnoff import ForceField as _Forcefield + + try: + from openff.toolkit.utils.nagl_wrapper import ( + NAGLToolkitWrapper as _NAGLToolkitWrapper, + ) + + _has_nagl = _NAGLToolkitWrapper.is_available() + from openff.nagl_models import get_models_by_type as _get_models_by_type + + _models = _get_models_by_type("am1bcc") + try: + # Find the most recent AM1-BCC release candidate. + _nagl = _NAGLToolkitWrapper() + _nagl_model = sorted( + [str(model) for model in _models if "rc" in str(model)], reverse=True + )[0] + except: + _has_nagl = False + del _models + except: + _has_nagl = False else: _Interchange = _openff _OpenFFMolecule = _openff @@ -289,6 +310,23 @@ def run(self, molecule, work_dir=None, queue=None): else: raise _ThirdPartyError(msg) from None + # Apply AM1-BCC charges using NAGL. + if _has_nagl: + try: + _nagl.assign_partial_charges( + off_molecule, partial_charge_method=_nagl_model + ) + except Exception as e: + msg = "Failed to assign AM1-BCC charges using NAGL." + if _isVerbose(): + msg += ": " + getattr(e, "message", repr(e)) + raise _ThirdPartyError(msg) from e + else: + raise _ThirdPartyError(msg) from None + charge_from_molecules = [off_molecule] + else: + charge_from_molecules = None + # Extract the molecular topology. try: off_topology = off_molecule.to_topology() @@ -315,7 +353,9 @@ def run(self, molecule, work_dir=None, queue=None): # Create an Interchange object. try: interchange = _Interchange.from_smirnoff( - force_field=forcefield, topology=off_topology + force_field=forcefield, + topology=off_topology, + charge_from_molecules=charge_from_molecules, ) except Exception as e: msg = "Unable to create OpenFF Interchange object!" From 9355e30fa726c860796ad44a77836e8adb25ee54 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Mon, 25 Mar 2024 09:19:32 +0000 Subject: [PATCH 03/14] Add default _has_nagl flag. --- python/BioSimSpace/Parameters/_Protocol/_openforcefield.py | 3 +++ .../Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py b/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py index 5cb2d6c8e..7c3aed05a 100644 --- a/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py +++ b/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py @@ -73,6 +73,9 @@ _openff = _try_import("openff") +# Initialise the NAGL support flag. +_has_nagl = False + if _have_imported(_openff): from openff.interchange import Interchange as _Interchange from openff.toolkit.topology import Molecule as _OpenFFMolecule diff --git a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py index 5cb2d6c8e..7c3aed05a 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py +++ b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py @@ -73,6 +73,9 @@ _openff = _try_import("openff") +# Initialise the NAGL support flag. +_has_nagl = False + if _have_imported(_openff): from openff.interchange import Interchange as _Interchange from openff.toolkit.topology import Molecule as _OpenFFMolecule From 0a3bd903a1f035d6a8c5820f03d98e198400c964 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Mon, 25 Mar 2024 09:49:12 +0000 Subject: [PATCH 04/14] Add support for clearing and disabling the file cache. [closes #265] --- python/BioSimSpace/IO/__init__.py | 4 ++ python/BioSimSpace/IO/_file_cache.py | 45 +++++++++++++++++-- python/BioSimSpace/IO/_io.py | 29 +++++++----- .../Sandpit/Exscientia/IO/__init__.py | 6 ++- .../Sandpit/Exscientia/IO/_file_cache.py | 45 +++++++++++++++++-- .../BioSimSpace/Sandpit/Exscientia/IO/_io.py | 31 ++++++++----- tests/IO/test_file_cache.py | 22 ++++++++- .../Sandpit/Exscientia/IO/test_file_cache.py | 22 ++++++++- 8 files changed, 169 insertions(+), 35 deletions(-) diff --git a/python/BioSimSpace/IO/__init__.py b/python/BioSimSpace/IO/__init__.py index 405005f35..95d60126d 100644 --- a/python/BioSimSpace/IO/__init__.py +++ b/python/BioSimSpace/IO/__init__.py @@ -28,6 +28,9 @@ .. autosummary:: :toctree: generated/ + clearCache + disableCache + enableCache fileFormats formatInfo readMolecules @@ -38,3 +41,4 @@ """ from ._io import * +from ._file_cache import * diff --git a/python/BioSimSpace/IO/_file_cache.py b/python/BioSimSpace/IO/_file_cache.py index 0b55aef9a..6f5b2d691 100644 --- a/python/BioSimSpace/IO/_file_cache.py +++ b/python/BioSimSpace/IO/_file_cache.py @@ -24,7 +24,7 @@ __author__ = "Lester Hedges" __email__ = "lester.hedges@gmail.com" -__all__ = ["check_cache", "update_cache"] +__all__ = ["clearCache", "disableCache", "enableCache"] import collections as _collections import hashlib as _hashlib @@ -80,8 +80,43 @@ def __delitem__(self, key): # to the same format, allowing us to re-use the existing file. _cache = _FixedSizeOrderedDict() +# Whether to use the cache. +_use_cache = True -def check_cache( + +def clearCache(): + """ + Clear the file cache. + """ + global _cache + _cache = _FixedSizeOrderedDict() + + +def disableCache(): + """ + Disable the file cache. + """ + global _use_cache + _use_cache = False + + +def enableCache(): + """ + Enable the file cache. + """ + global _use_cache + _use_cache = True + + +def _cache_active(): + """ + Internal helper function to check whether the cache is active. + """ + global _use_cache + return _use_cache + + +def _check_cache( system, format, filebase, @@ -157,6 +192,8 @@ def check_cache( if not isinstance(skip_water, bool): raise TypeError("'skip_water' must be of type 'bool'.") + global _cache + # Create the key. key = ( system._sire_object.uid().toString(), @@ -221,7 +258,7 @@ def check_cache( return ext -def update_cache( +def _update_cache( system, format, path, @@ -284,6 +321,8 @@ def update_cache( if not isinstance(skip_water, bool): raise TypeError("'skip_water' must be of type 'bool'.") + global _cache + # Convert to an absolute path. path = _os.path.abspath(path) diff --git a/python/BioSimSpace/IO/_io.py b/python/BioSimSpace/IO/_io.py index 3fcf08e23..9aca4a3d4 100644 --- a/python/BioSimSpace/IO/_io.py +++ b/python/BioSimSpace/IO/_io.py @@ -66,8 +66,9 @@ from .._SireWrappers import System as _System from .. import _Utils -from ._file_cache import check_cache as _check_cache -from ._file_cache import update_cache as _update_cache +from ._file_cache import _check_cache +from ._file_cache import _update_cache +from ._file_cache import _cache_active # Context manager for capturing stdout. @@ -741,14 +742,17 @@ def saveMolecules( # Save the system using each file format. for format in formats: # Copy an existing file if it exists in the cache. - ext = _check_cache( - system, - format, - filebase, - match_water=match_water, - property_map=property_map, - **kwargs, - ) + if _cache_active(): + ext = _check_cache( + system, + format, + filebase, + match_water=match_water, + property_map=property_map, + **kwargs, + ) + else: + ext = None if ext: files.append(_os.path.abspath(filebase + ext)) continue @@ -835,7 +839,10 @@ def saveMolecules( files += file # If this is a new file, then add it to the cache. - _update_cache(system, format, file[0], match_water=match_water, **kwargs) + if _cache_active(): + _update_cache( + system, format, file[0], match_water=match_water, **kwargs + ) except Exception as e: msg = "Failed to save system to format: '%s'" % format diff --git a/python/BioSimSpace/Sandpit/Exscientia/IO/__init__.py b/python/BioSimSpace/Sandpit/Exscientia/IO/__init__.py index e83faacca..95d60126d 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/IO/__init__.py +++ b/python/BioSimSpace/Sandpit/Exscientia/IO/__init__.py @@ -28,6 +28,9 @@ .. autosummary:: :toctree: generated/ + clearCache + disableCache + enableCache fileFormats formatInfo readMolecules @@ -37,6 +40,5 @@ savePerturbableSystem """ -from glob import glob - from ._io import * +from ._file_cache import * diff --git a/python/BioSimSpace/Sandpit/Exscientia/IO/_file_cache.py b/python/BioSimSpace/Sandpit/Exscientia/IO/_file_cache.py index 0b55aef9a..6f5b2d691 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/IO/_file_cache.py +++ b/python/BioSimSpace/Sandpit/Exscientia/IO/_file_cache.py @@ -24,7 +24,7 @@ __author__ = "Lester Hedges" __email__ = "lester.hedges@gmail.com" -__all__ = ["check_cache", "update_cache"] +__all__ = ["clearCache", "disableCache", "enableCache"] import collections as _collections import hashlib as _hashlib @@ -80,8 +80,43 @@ def __delitem__(self, key): # to the same format, allowing us to re-use the existing file. _cache = _FixedSizeOrderedDict() +# Whether to use the cache. +_use_cache = True -def check_cache( + +def clearCache(): + """ + Clear the file cache. + """ + global _cache + _cache = _FixedSizeOrderedDict() + + +def disableCache(): + """ + Disable the file cache. + """ + global _use_cache + _use_cache = False + + +def enableCache(): + """ + Enable the file cache. + """ + global _use_cache + _use_cache = True + + +def _cache_active(): + """ + Internal helper function to check whether the cache is active. + """ + global _use_cache + return _use_cache + + +def _check_cache( system, format, filebase, @@ -157,6 +192,8 @@ def check_cache( if not isinstance(skip_water, bool): raise TypeError("'skip_water' must be of type 'bool'.") + global _cache + # Create the key. key = ( system._sire_object.uid().toString(), @@ -221,7 +258,7 @@ def check_cache( return ext -def update_cache( +def _update_cache( system, format, path, @@ -284,6 +321,8 @@ def update_cache( if not isinstance(skip_water, bool): raise TypeError("'skip_water' must be of type 'bool'.") + global _cache + # Convert to an absolute path. path = _os.path.abspath(path) diff --git a/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py b/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py index 97ac66348..9aca4a3d4 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py +++ b/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py @@ -66,8 +66,9 @@ from .._SireWrappers import System as _System from .. import _Utils -from ._file_cache import check_cache as _check_cache -from ._file_cache import update_cache as _update_cache +from ._file_cache import _check_cache +from ._file_cache import _update_cache +from ._file_cache import _cache_active # Context manager for capturing stdout. @@ -741,14 +742,17 @@ def saveMolecules( # Save the system using each file format. for format in formats: # Copy an existing file if it exists in the cache. - ext = _check_cache( - system, - format, - filebase, - match_water=match_water, - property_map=property_map, - **kwargs, - ) + if _cache_active(): + ext = _check_cache( + system, + format, + filebase, + match_water=match_water, + property_map=property_map, + **kwargs, + ) + else: + ext = None if ext: files.append(_os.path.abspath(filebase + ext)) continue @@ -835,7 +839,10 @@ def saveMolecules( files += file # If this is a new file, then add it to the cache. - _update_cache(system, format, file[0], match_water=match_water, **kwargs) + if _cache_active(): + _update_cache( + system, format, file[0], match_water=match_water, **kwargs + ) except Exception as e: msg = "Failed to save system to format: '%s'" % format @@ -1162,7 +1169,7 @@ def readPerturbableSystem(top0, coords0, top1, coords1, property_map={}): prop = property_map.get("time", "time") time = system0._sire_object.property(prop) system0._sire_object.removeSharedProperty(prop) - system0._sire_object.setPropery(prop, time) + system0._sire_object.setProperty(prop, time) except: pass diff --git a/tests/IO/test_file_cache.py b/tests/IO/test_file_cache.py index 9d3866c99..a431cfc03 100644 --- a/tests/IO/test_file_cache.py +++ b/tests/IO/test_file_cache.py @@ -15,7 +15,7 @@ def test_file_cache(): """ # Clear the file cache. - BSS.IO._file_cache._cache = BSS.IO._file_cache._FixedSizeOrderedDict() + BSS.IO.clearCache() # Load the molecular system. s = BSS.IO.readMolecules(["tests/input/ala.crd", "tests/input/ala.top"]) @@ -82,6 +82,21 @@ def test_file_cache(): # Make sure the number of atoms in the cache was decremented. assert BSS.IO._file_cache._cache._num_atoms == total_atoms - num_atoms + # Clear the file cache. + BSS.IO.clearCache() + + # The cache should now be empty. + assert len(BSS.IO._file_cache._cache) == 0 + + # Disable the cache. + BSS.IO.disableCache() + + # Write to PDB and GroTop format. The PDB from the cache should not be reused. + BSS.IO.saveMolecules(f"{tmp_path}/tmp5", s, ["pdb", "grotop"]) + + # The cache should still be empty. + assert len(BSS.IO._file_cache._cache) == 0 + @pytest.mark.skipif( has_amber is False or has_openff is False, @@ -93,8 +108,11 @@ def test_file_cache_mol_nums(): contain different MolNUms. """ + # Enable the cache. + BSS.IO.enableCache() + # Clear the file cache. - BSS.IO._file_cache._cache = BSS.IO._file_cache._FixedSizeOrderedDict() + BSS.IO.clearCache() # Create an initial system. system = BSS.Parameters.openff_unconstrained_2_0_0("CO").getMolecule().toSystem() diff --git a/tests/Sandpit/Exscientia/IO/test_file_cache.py b/tests/Sandpit/Exscientia/IO/test_file_cache.py index 20ed2f9f3..6e292b66c 100644 --- a/tests/Sandpit/Exscientia/IO/test_file_cache.py +++ b/tests/Sandpit/Exscientia/IO/test_file_cache.py @@ -16,7 +16,7 @@ def test_file_cache(): """ # Clear the file cache. - BSS.IO._file_cache._cache = BSS.IO._file_cache._FixedSizeOrderedDict() + BSS.IO.clearCache() # Load the molecular system. s = BSS.IO.readMolecules([f"{root_fp}/input/ala.crd", f"{root_fp}/input/ala.top"]) @@ -83,6 +83,21 @@ def test_file_cache(): # Make sure the number of atoms in the cache was decremented. assert BSS.IO._file_cache._cache._num_atoms == total_atoms - num_atoms + # Clear the file cache. + BSS.IO.clearCache() + + # The cache should now be empty. + assert len(BSS.IO._file_cache._cache) == 0 + + # Disable the cache. + BSS.IO.disableCache() + + # Write to PDB and GroTop format. The PDB from the cache should not be reused. + BSS.IO.saveMolecules(f"{tmp_path}/tmp5", s, ["pdb", "grotop"]) + + # The cache should still be empty. + assert len(BSS.IO._file_cache._cache) == 0 + @pytest.mark.skipif( has_amber is False or has_openff is False, @@ -94,8 +109,11 @@ def test_file_cache_mol_nums(): contain different MolNUms. """ + # Enable the cache. + BSS.IO.enableCache() + # Clear the file cache. - BSS.IO._file_cache._cache = BSS.IO._file_cache._FixedSizeOrderedDict() + BSS.IO.clearCache() # Create an initial system. system = BSS.Parameters.openff_unconstrained_2_0_0("CO").getMolecule().toSystem() From 0e2bb922ce314536c9efa3126c19edf0b783be1b Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Mon, 25 Mar 2024 15:57:01 +0000 Subject: [PATCH 05/14] Allow user to choose to use NAGL to generate AM1-BCC charges. --- .../Parameters/_Protocol/_openforcefield.py | 17 ++++++++++-- python/BioSimSpace/Parameters/_parameters.py | 27 +++++++++++++++++-- .../Parameters/_Protocol/_openforcefield.py | 17 ++++++++++-- .../Exscientia/Parameters/_parameters.py | 27 +++++++++++++++++-- 4 files changed, 80 insertions(+), 8 deletions(-) diff --git a/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py b/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py index 7c3aed05a..018f43e4e 100644 --- a/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py +++ b/python/BioSimSpace/Parameters/_Protocol/_openforcefield.py @@ -127,7 +127,9 @@ class OpenForceField(_protocol.Protocol): """A class for handling protocols for Open Force Field models.""" - def __init__(self, forcefield, ensure_compatible=True, property_map={}): + def __init__( + self, forcefield, ensure_compatible=True, use_nagl=True, property_map={} + ): """ Constructor. @@ -145,6 +147,11 @@ def __init__(self, forcefield, ensure_compatible=True, property_map={}): original molecule, e.g. the original atom and residue names will be kept. + use_nagl : bool + Whether to use NAGL to compute AM1-BCC charges. If False, the default + is to use AmberTools via antechamber and sqm. (This option is only + used if NAGL is available.) + property_map : dict A dictionary that maps system "properties" to their user defined values. This allows the user to refer to properties with their @@ -158,6 +165,12 @@ def __init__(self, forcefield, ensure_compatible=True, property_map={}): property_map=property_map, ) + if not isinstance(use_nagl, bool): + raise TypeError("'use_nagl' must be of type 'bool'") + + # Set the NAGL flag. + self._use_nagl = use_nagl + # Set the compatibility flags. self._tleap = False self._pdb2gmx = False @@ -314,7 +327,7 @@ def run(self, molecule, work_dir=None, queue=None): raise _ThirdPartyError(msg) from None # Apply AM1-BCC charges using NAGL. - if _has_nagl: + if _has_nagl and self._use_nagl: try: _nagl.assign_partial_charges( off_molecule, partial_charge_method=_nagl_model diff --git a/python/BioSimSpace/Parameters/_parameters.py b/python/BioSimSpace/Parameters/_parameters.py index 07a49d24b..6e8570bb9 100644 --- a/python/BioSimSpace/Parameters/_parameters.py +++ b/python/BioSimSpace/Parameters/_parameters.py @@ -463,6 +463,7 @@ def _parameterise_openff( forcefield, molecule, ensure_compatible=True, + use_nagl=True, work_dir=None, property_map={}, **kwargs, @@ -489,6 +490,11 @@ def _parameterise_openff( the parameterised molecule will preserve the topology of the original molecule, e.g. the original atom and residue names will be kept. + use_nagl : bool + Whether to use NAGL to compute AM1-BCC charges. If False, the default + is to use AmberTools via antechamber and sqm. (This option is only + used if NAGL is available.) + work_dir : str The working directory for the process. @@ -583,12 +589,21 @@ def _parameterise_openff( if forcefield not in _forcefields_lower: raise ValueError("Supported force fields are: %s" % openForceFields()) + if not isinstance(ensure_compatible, bool): + raise TypeError("'ensure_compatible' must be of type 'bool'.") + + if not isinstance(use_nagl, bool): + raise TypeError("'use_nagl' must be of type 'bool'.") + if not isinstance(property_map, dict): raise TypeError("'property_map' must be of type 'dict'") # Create a default protocol. protocol = _Protocol.OpenForceField( - forcefield, ensure_compatible=ensure_compatible, property_map=property_map + forcefield, + ensure_compatible=ensure_compatible, + use_nagl=use_nagl, + property_map=property_map, ) # Run the parameterisation protocol in the background and return @@ -1079,7 +1094,9 @@ def _function( # it conforms to sensible function naming standards, i.e. "-" and "." # characters replaced by underscores. def _make_openff_function(name): - def _function(molecule, ensure_compatible=True, work_dir=None, property_map={}): + def _function( + molecule, ensure_compatible=True, use_nagl=True, work_dir=None, property_map={} + ): """ Parameterise a molecule using the named force field from the Open Force Field initiative. @@ -1100,6 +1117,11 @@ def _function(molecule, ensure_compatible=True, work_dir=None, property_map={}): molecule will preserve the topology of the original molecule, e.g. the original atom and residue names will be kept. + use_nagl : bool + Whether to use NAGL to compute AM1-BCC charges. If False, the default + is to use AmberTools via antechamber and sqm. (This option is only + used if NAGL is available.) + work_dir : str The working directory for the process. @@ -1118,6 +1140,7 @@ def _function(molecule, ensure_compatible=True, work_dir=None, property_map={}): name, molecule, ensure_compatible=ensure_compatible, + use_nagl=use_nagl, work_dir=work_dir, property_map=property_map, ) diff --git a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py index 7c3aed05a..018f43e4e 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py +++ b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_Protocol/_openforcefield.py @@ -127,7 +127,9 @@ class OpenForceField(_protocol.Protocol): """A class for handling protocols for Open Force Field models.""" - def __init__(self, forcefield, ensure_compatible=True, property_map={}): + def __init__( + self, forcefield, ensure_compatible=True, use_nagl=True, property_map={} + ): """ Constructor. @@ -145,6 +147,11 @@ def __init__(self, forcefield, ensure_compatible=True, property_map={}): original molecule, e.g. the original atom and residue names will be kept. + use_nagl : bool + Whether to use NAGL to compute AM1-BCC charges. If False, the default + is to use AmberTools via antechamber and sqm. (This option is only + used if NAGL is available.) + property_map : dict A dictionary that maps system "properties" to their user defined values. This allows the user to refer to properties with their @@ -158,6 +165,12 @@ def __init__(self, forcefield, ensure_compatible=True, property_map={}): property_map=property_map, ) + if not isinstance(use_nagl, bool): + raise TypeError("'use_nagl' must be of type 'bool'") + + # Set the NAGL flag. + self._use_nagl = use_nagl + # Set the compatibility flags. self._tleap = False self._pdb2gmx = False @@ -314,7 +327,7 @@ def run(self, molecule, work_dir=None, queue=None): raise _ThirdPartyError(msg) from None # Apply AM1-BCC charges using NAGL. - if _has_nagl: + if _has_nagl and self._use_nagl: try: _nagl.assign_partial_charges( off_molecule, partial_charge_method=_nagl_model diff --git a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_parameters.py b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_parameters.py index 07a49d24b..6e8570bb9 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/Parameters/_parameters.py +++ b/python/BioSimSpace/Sandpit/Exscientia/Parameters/_parameters.py @@ -463,6 +463,7 @@ def _parameterise_openff( forcefield, molecule, ensure_compatible=True, + use_nagl=True, work_dir=None, property_map={}, **kwargs, @@ -489,6 +490,11 @@ def _parameterise_openff( the parameterised molecule will preserve the topology of the original molecule, e.g. the original atom and residue names will be kept. + use_nagl : bool + Whether to use NAGL to compute AM1-BCC charges. If False, the default + is to use AmberTools via antechamber and sqm. (This option is only + used if NAGL is available.) + work_dir : str The working directory for the process. @@ -583,12 +589,21 @@ def _parameterise_openff( if forcefield not in _forcefields_lower: raise ValueError("Supported force fields are: %s" % openForceFields()) + if not isinstance(ensure_compatible, bool): + raise TypeError("'ensure_compatible' must be of type 'bool'.") + + if not isinstance(use_nagl, bool): + raise TypeError("'use_nagl' must be of type 'bool'.") + if not isinstance(property_map, dict): raise TypeError("'property_map' must be of type 'dict'") # Create a default protocol. protocol = _Protocol.OpenForceField( - forcefield, ensure_compatible=ensure_compatible, property_map=property_map + forcefield, + ensure_compatible=ensure_compatible, + use_nagl=use_nagl, + property_map=property_map, ) # Run the parameterisation protocol in the background and return @@ -1079,7 +1094,9 @@ def _function( # it conforms to sensible function naming standards, i.e. "-" and "." # characters replaced by underscores. def _make_openff_function(name): - def _function(molecule, ensure_compatible=True, work_dir=None, property_map={}): + def _function( + molecule, ensure_compatible=True, use_nagl=True, work_dir=None, property_map={} + ): """ Parameterise a molecule using the named force field from the Open Force Field initiative. @@ -1100,6 +1117,11 @@ def _function(molecule, ensure_compatible=True, work_dir=None, property_map={}): molecule will preserve the topology of the original molecule, e.g. the original atom and residue names will be kept. + use_nagl : bool + Whether to use NAGL to compute AM1-BCC charges. If False, the default + is to use AmberTools via antechamber and sqm. (This option is only + used if NAGL is available.) + work_dir : str The working directory for the process. @@ -1118,6 +1140,7 @@ def _function(molecule, ensure_compatible=True, work_dir=None, property_map={}): name, molecule, ensure_compatible=ensure_compatible, + use_nagl=use_nagl, work_dir=work_dir, property_map=property_map, ) From af9cced9bfeab433792a9475ca6d20bca64d7b0b Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Mon, 25 Mar 2024 16:38:43 +0000 Subject: [PATCH 06/14] Upgrade setup-miniconda action. --- .github/workflows/devel.yaml | 2 +- .github/workflows/main.yaml | 2 +- .github/workflows/pr.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/devel.yaml b/.github/workflows/devel.yaml index ce34c30cc..a9640d353 100644 --- a/.github/workflows/devel.yaml +++ b/.github/workflows/devel.yaml @@ -36,7 +36,7 @@ jobs: SIRE_DONT_PHONEHOME: 1 SIRE_SILENT_PHONEHOME: 1 steps: - - uses: conda-incubator/setup-miniconda@v2 + - uses: conda-incubator/setup-miniconda@v3 with: auto-update-conda: true python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 8b36c02b1..0b6dc5d86 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -30,7 +30,7 @@ jobs: SIRE_DONT_PHONEHOME: 1 SIRE_SILENT_PHONEHOME: 1 steps: - - uses: conda-incubator/setup-miniconda@v2 + - uses: conda-incubator/setup-miniconda@v3 with: auto-update-conda: true python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 5e9268b58..2a7dd5474 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -40,7 +40,7 @@ jobs: SIRE_SILENT_PHONEHOME: 1 REPO: "${{ github.event.pull_request.head.repo.full_name || github.repository }}" steps: - - uses: conda-incubator/setup-miniconda@v2 + - uses: conda-incubator/setup-miniconda@v3 with: auto-update-conda: true python-version: ${{ matrix.python-version }} From 04b423dfb4d4145b41dbe1f1fe1b3554b802cbbc Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Mon, 25 Mar 2024 16:44:04 +0000 Subject: [PATCH 07/14] Manually add boltons. --- .github/workflows/devel.yaml | 2 +- .github/workflows/main.yaml | 2 +- .github/workflows/pr.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/devel.yaml b/.github/workflows/devel.yaml index a9640d353..d2a269b50 100644 --- a/.github/workflows/devel.yaml +++ b/.github/workflows/devel.yaml @@ -49,7 +49,7 @@ jobs: run: git clone -b devel https://github.com/openbiosim/biosimspace # - name: Setup Conda - run: mamba install -y -c conda-forge boa anaconda-client packaging=21 pip-requirements-parser + run: mamba install -y -c conda-forge boa boltons anaconda-client packaging=21 pip-requirements-parser # - name: Update Conda recipe run: python ${{ github.workspace }}/biosimspace/actions/update_recipe.py diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 0b6dc5d86..f9181191e 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -43,7 +43,7 @@ jobs: run: git clone -b main https://github.com/openbiosim/biosimspace # - name: Setup Conda - run: mamba install -y -c conda-forge boa anaconda-client packaging=21 pip-requirements-parser + run: mamba install -y -c conda-forge boa boltons anaconda-client packaging=21 pip-requirements-parser # - name: Update Conda recipe run: python ${{ github.workspace }}/biosimspace/actions/update_recipe.py diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 2a7dd5474..fd6fbbf29 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -53,7 +53,7 @@ jobs: run: git clone -b ${{ github.head_ref }} --single-branch https://github.com/${{ env.REPO }} biosimspace # - name: Setup Conda - run: mamba install -y -c conda-forge boa anaconda-client packaging=21 pip-requirements-parser + run: mamba install -y -c conda-forge boa boltons anaconda-client packaging=21 pip-requirements-parser # - name: Update Conda recipe run: python ${{ github.workspace }}/biosimspace/actions/update_recipe.py From f987c2b7c33fd8481a82462e73f99af75308b222 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Tue, 26 Mar 2024 11:59:41 +0000 Subject: [PATCH 08/14] Pin to boa version 0.16. --- .github/workflows/devel.yaml | 2 +- .github/workflows/main.yaml | 2 +- .github/workflows/pr.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/devel.yaml b/.github/workflows/devel.yaml index d2a269b50..31869037b 100644 --- a/.github/workflows/devel.yaml +++ b/.github/workflows/devel.yaml @@ -49,7 +49,7 @@ jobs: run: git clone -b devel https://github.com/openbiosim/biosimspace # - name: Setup Conda - run: mamba install -y -c conda-forge boa boltons anaconda-client packaging=21 pip-requirements-parser + run: mamba install -y -c conda-forge boa=0.16 anaconda-client packaging=21 pip-requirements-parser # - name: Update Conda recipe run: python ${{ github.workspace }}/biosimspace/actions/update_recipe.py diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index f9181191e..a5c441797 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -43,7 +43,7 @@ jobs: run: git clone -b main https://github.com/openbiosim/biosimspace # - name: Setup Conda - run: mamba install -y -c conda-forge boa boltons anaconda-client packaging=21 pip-requirements-parser + run: mamba install -y -c conda-forge boa=0.16 anaconda-client packaging=21 pip-requirements-parser # - name: Update Conda recipe run: python ${{ github.workspace }}/biosimspace/actions/update_recipe.py diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index fd6fbbf29..3ef002f5e 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -53,7 +53,7 @@ jobs: run: git clone -b ${{ github.head_ref }} --single-branch https://github.com/${{ env.REPO }} biosimspace # - name: Setup Conda - run: mamba install -y -c conda-forge boa boltons anaconda-client packaging=21 pip-requirements-parser + run: mamba install -y -c conda-forge boa=0.16 anaconda-client packaging=21 pip-requirements-parser # - name: Update Conda recipe run: python ${{ github.workspace }}/biosimspace/actions/update_recipe.py From 46da6e724d92ac6b96e1336df867c014ad683cbd Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Thu, 28 Mar 2024 09:40:02 +0000 Subject: [PATCH 09/14] Glob after converting files to a list. --- python/BioSimSpace/IO/_io.py | 9 ++++++--- python/BioSimSpace/Sandpit/Exscientia/IO/_io.py | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/python/BioSimSpace/IO/_io.py b/python/BioSimSpace/IO/_io.py index 9aca4a3d4..433781188 100644 --- a/python/BioSimSpace/IO/_io.py +++ b/python/BioSimSpace/IO/_io.py @@ -431,11 +431,8 @@ def readMolecules( ) _has_gmx_warned = True - # Glob string to catch wildcards and convert to list. if isinstance(files, str): if not files.startswith(("http", "www")): - files = _glob(files) - else: files = [files] # Check that all arguments are of type 'str'. @@ -450,6 +447,12 @@ def readMolecules( else: raise TypeError("'files' must be of type 'str', or a list of 'str' types.") + # Glob all files to catch wildcards. + new_files = [] + for file in files: + new_files += _glob(file) + files = new_files + # Validate the molecule unwrapping flag. if not isinstance(make_whole, bool): raise TypeError("'make_whole' must be of type 'bool'.") diff --git a/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py b/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py index 9aca4a3d4..433781188 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py +++ b/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py @@ -431,11 +431,8 @@ def readMolecules( ) _has_gmx_warned = True - # Glob string to catch wildcards and convert to list. if isinstance(files, str): if not files.startswith(("http", "www")): - files = _glob(files) - else: files = [files] # Check that all arguments are of type 'str'. @@ -450,6 +447,12 @@ def readMolecules( else: raise TypeError("'files' must be of type 'str', or a list of 'str' types.") + # Glob all files to catch wildcards. + new_files = [] + for file in files: + new_files += _glob(file) + files = new_files + # Validate the molecule unwrapping flag. if not isinstance(make_whole, bool): raise TypeError("'make_whole' must be of type 'bool'.") From 426e30aa9f8c0c57d84cec6e9c069cb1d45b1cb9 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Thu, 28 Mar 2024 09:58:54 +0000 Subject: [PATCH 10/14] Add support for adding molecules from a SearchResult. --- .../Exscientia/_SireWrappers/_system.py | 30 +++++++++++++++---- python/BioSimSpace/_SireWrappers/_system.py | 30 +++++++++++++++---- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/python/BioSimSpace/Sandpit/Exscientia/_SireWrappers/_system.py b/python/BioSimSpace/Sandpit/Exscientia/_SireWrappers/_system.py index e51f141c7..56bf3aebe 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/_SireWrappers/_system.py +++ b/python/BioSimSpace/Sandpit/Exscientia/_SireWrappers/_system.py @@ -554,12 +554,17 @@ def addMolecules(self, molecules): molecules : :class:`Molecule `, \ :class:`Molecules `, \ [:class:`Molecule `], \ - :class:`System ` - A Molecule, Molecules object, a list of Molecule objects, or a System containing molecules. + :class:`System `, \ + :class:`SearchResult ` + A Molecule, Molecules object, a list of Molecule objects, a System, + or a SearchResult containing molecules. """ - # Whether the molecules are in a Sire container. - is_sire_container = False + from ._search_result import SearchResult as _SearchResult + from sire.legacy.Mol import SelectorMol as _SelectorMol + + # Whether this is a selector mol object. + is_selector_mol = False # Convert tuple to a list. if isinstance(molecules, tuple): @@ -583,6 +588,17 @@ def addMolecules(self, molecules): ): molecules = _Molecules(molecules) + # A SearchResult object. + elif isinstance(molecules, _SearchResult): + if isinstance(molecules._sire_object, _SelectorMol): + is_selector_mol = True + pass + else: + raise ValueError( + "Invalid 'SearchResult' object. Can only add a molecule " + "search, i.e. a wrapped 'sire.legacy.Mol.SelectorMol'." + ) + # Invalid argument. else: raise TypeError( @@ -619,7 +635,11 @@ def addMolecules(self, molecules): ) # Add the molecules to the system. - self._sire_object.add(molecules._sire_object, _SireMol.MGName("all")) + if is_selector_mol: + for mol in molecules: + self._sire_object.add(mol._sire_object, _SireMol.MGName("all")) + else: + self._sire_object.add(molecules._sire_object, _SireMol.MGName("all")) # Reset the index mappings. self._reset_mappings() diff --git a/python/BioSimSpace/_SireWrappers/_system.py b/python/BioSimSpace/_SireWrappers/_system.py index 52ed9c083..380a3b736 100644 --- a/python/BioSimSpace/_SireWrappers/_system.py +++ b/python/BioSimSpace/_SireWrappers/_system.py @@ -554,12 +554,17 @@ def addMolecules(self, molecules): molecules : :class:`Molecule `, \ :class:`Molecules `, \ [:class:`Molecule `], \ - :class:`System ` - A Molecule, Molecules object, a list of Molecule objects, or a System containing molecules. + :class:`System `, \ + :class:`SearchResult ` + A Molecule, Molecules object, a list of Molecule objects, a System, + or a SearchResult containing molecules. """ - # Whether the molecules are in a Sire container. - is_sire_container = False + from ._search_result import SearchResult as _SearchResult + from sire.legacy.Mol import SelectorMol as _SelectorMol + + # Whether this is a selector mol object. + is_selector_mol = False # Convert tuple to a list. if isinstance(molecules, tuple): @@ -583,6 +588,17 @@ def addMolecules(self, molecules): ): molecules = _Molecules(molecules) + # A SearchResult object. + elif isinstance(molecules, _SearchResult): + if isinstance(molecules._sire_object, _SelectorMol): + is_selector_mol = True + pass + else: + raise ValueError( + "Invalid 'SearchResult' object. Can only add a molecule " + "search, i.e. a wrapped 'sire.legacy.Mol.SelectorMol'." + ) + # Invalid argument. else: raise TypeError( @@ -619,7 +635,11 @@ def addMolecules(self, molecules): ) # Add the molecules to the system. - self._sire_object.add(molecules._sire_object, _SireMol.MGName("all")) + if is_selector_mol: + for mol in molecules: + self._sire_object.add(mol._sire_object, _SireMol.MGName("all")) + else: + self._sire_object.add(molecules._sire_object, _SireMol.MGName("all")) # Reset the index mappings. self._reset_mappings() From 29aff165b7bd4655fc89b8e47ed30533dc5f3b03 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Thu, 28 Mar 2024 11:06:42 +0000 Subject: [PATCH 11/14] Need to exlude URLs from glob. --- python/BioSimSpace/IO/_io.py | 5 ++++- python/BioSimSpace/Sandpit/Exscientia/IO/_io.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/python/BioSimSpace/IO/_io.py b/python/BioSimSpace/IO/_io.py index 433781188..2e0567efc 100644 --- a/python/BioSimSpace/IO/_io.py +++ b/python/BioSimSpace/IO/_io.py @@ -450,7 +450,10 @@ def readMolecules( # Glob all files to catch wildcards. new_files = [] for file in files: - new_files += _glob(file) + if not file.startswith(("http", "www")): + new_files += _glob(file) + else: + new_files.append(file) files = new_files # Validate the molecule unwrapping flag. diff --git a/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py b/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py index 433781188..2e0567efc 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py +++ b/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py @@ -450,7 +450,10 @@ def readMolecules( # Glob all files to catch wildcards. new_files = [] for file in files: - new_files += _glob(file) + if not file.startswith(("http", "www")): + new_files += _glob(file) + else: + new_files.append(file) files = new_files # Validate the molecule unwrapping flag. From 9b6cf96e71e847069bb406127bbf1bd218a09bf0 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Thu, 28 Mar 2024 12:11:15 +0000 Subject: [PATCH 12/14] Convert all single string parameters to a list. --- python/BioSimSpace/IO/_io.py | 4 ++-- python/BioSimSpace/Sandpit/Exscientia/IO/_io.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/BioSimSpace/IO/_io.py b/python/BioSimSpace/IO/_io.py index 2e0567efc..ff475f349 100644 --- a/python/BioSimSpace/IO/_io.py +++ b/python/BioSimSpace/IO/_io.py @@ -431,9 +431,9 @@ def readMolecules( ) _has_gmx_warned = True + # Convert a single string to a list. if isinstance(files, str): - if not files.startswith(("http", "www")): - files = [files] + files = [files] # Check that all arguments are of type 'str'. if isinstance(files, (list, tuple)): diff --git a/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py b/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py index 2e0567efc..ff475f349 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py +++ b/python/BioSimSpace/Sandpit/Exscientia/IO/_io.py @@ -431,9 +431,9 @@ def readMolecules( ) _has_gmx_warned = True + # Convert a single string to a list. if isinstance(files, str): - if not files.startswith(("http", "www")): - files = [files] + files = [files] # Check that all arguments are of type 'str'. if isinstance(files, (list, tuple)): From 5d3ed74e8731a9709685bb5ec2f5b1d3daadcdf8 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Mon, 8 Apr 2024 09:57:33 +0100 Subject: [PATCH 13/14] Remove boa and packaging pins. [ci skip] --- .github/workflows/devel.yaml | 2 +- .github/workflows/main.yaml | 2 +- .github/workflows/pr.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/devel.yaml b/.github/workflows/devel.yaml index 31869037b..9aa98c8e2 100644 --- a/.github/workflows/devel.yaml +++ b/.github/workflows/devel.yaml @@ -49,7 +49,7 @@ jobs: run: git clone -b devel https://github.com/openbiosim/biosimspace # - name: Setup Conda - run: mamba install -y -c conda-forge boa=0.16 anaconda-client packaging=21 pip-requirements-parser + run: mamba install -y -c conda-forge boa anaconda-client packaging pip-requirements-parser # - name: Update Conda recipe run: python ${{ github.workspace }}/biosimspace/actions/update_recipe.py diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index a5c441797..f98022f4f 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -43,7 +43,7 @@ jobs: run: git clone -b main https://github.com/openbiosim/biosimspace # - name: Setup Conda - run: mamba install -y -c conda-forge boa=0.16 anaconda-client packaging=21 pip-requirements-parser + run: mamba install -y -c conda-forge boa anaconda-client packaging pip-requirements-parser # - name: Update Conda recipe run: python ${{ github.workspace }}/biosimspace/actions/update_recipe.py diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 3ef002f5e..ead208b87 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -53,7 +53,7 @@ jobs: run: git clone -b ${{ github.head_ref }} --single-branch https://github.com/${{ env.REPO }} biosimspace # - name: Setup Conda - run: mamba install -y -c conda-forge boa=0.16 anaconda-client packaging=21 pip-requirements-parser + run: mamba install -y -c conda-forge boa anaconda-client packaging pip-requirements-parser # - name: Update Conda recipe run: python ${{ github.workspace }}/biosimspace/actions/update_recipe.py From e2919b57df325dc990f84e0139123f7b97603944 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Mon, 8 Apr 2024 10:22:41 +0100 Subject: [PATCH 14/14] Filter base units list by type and base class. [closes #269] --- .../Sandpit/Exscientia/Types/_base_units.py | 10 ++++++++-- python/BioSimSpace/Types/_base_units.py | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/python/BioSimSpace/Sandpit/Exscientia/Types/_base_units.py b/python/BioSimSpace/Sandpit/Exscientia/Types/_base_units.py index 931668f84..267cb5516 100644 --- a/python/BioSimSpace/Sandpit/Exscientia/Types/_base_units.py +++ b/python/BioSimSpace/Sandpit/Exscientia/Types/_base_units.py @@ -24,6 +24,8 @@ __all__ = ["_base_units", "_base_dimensions", "_sire_units_locals"] +import sys as _sys + from ._angle import * from ._area import * from ._charge import * @@ -33,13 +35,17 @@ from ._temperature import * from ._time import * from ._volume import * - -import sys as _sys +from ._type import Type as _Type _namespace = _sys.modules[__name__] # Create the list of base unit types. _base_units = [getattr(_namespace, var) for var in dir() if var[0] != "_"] +# Filter out any non-Type objects. (This can happen when BioSimSpace is +# wrapped by other tools, e.g. Maize.) +_base_units = [ + unit for unit in _base_units if isinstance(unit, type) and unit.__base__ == _Type +] _base_dimensions = {} for unit in _base_units: diff --git a/python/BioSimSpace/Types/_base_units.py b/python/BioSimSpace/Types/_base_units.py index 931668f84..267cb5516 100644 --- a/python/BioSimSpace/Types/_base_units.py +++ b/python/BioSimSpace/Types/_base_units.py @@ -24,6 +24,8 @@ __all__ = ["_base_units", "_base_dimensions", "_sire_units_locals"] +import sys as _sys + from ._angle import * from ._area import * from ._charge import * @@ -33,13 +35,17 @@ from ._temperature import * from ._time import * from ._volume import * - -import sys as _sys +from ._type import Type as _Type _namespace = _sys.modules[__name__] # Create the list of base unit types. _base_units = [getattr(_namespace, var) for var in dir() if var[0] != "_"] +# Filter out any non-Type objects. (This can happen when BioSimSpace is +# wrapped by other tools, e.g. Maize.) +_base_units = [ + unit for unit in _base_units if isinstance(unit, type) and unit.__base__ == _Type +] _base_dimensions = {} for unit in _base_units: