Skip to content

Commit

Permalink
Fixed circular import of sire.cas. Fixed missing function in the mixe…
Browse files Browse the repository at this point in the history
…d api.

Fixed issue where a System has a space, but it isn't shared, meaning that
it is lost when the System is converted to OpenMM
  • Loading branch information
chryswoods committed Sep 18, 2023
1 parent 32646f1 commit bcc2acd
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 120 deletions.
184 changes: 76 additions & 108 deletions src/sire/_pythonize.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,115 +156,14 @@ def _pythonize_modules(modules, delete_old: bool = True):
_is_using_new_api = None


def use_mixed_api(support_old_module_names: bool = False):
"""Load Sire using both the new (python-style) and old APIs. This
is useful for migrating old scripts as a temporary porting option.
You can start writing functions using the new API, safe in the
knowledge that the old API functions will still work.
Do aim to finish your port though, else you will forever have
a duplicated API (e.g. have both X.nAtoms() and X.num_atoms() etc.)
def _load_new_api_modules(delete_old: bool = True):
"""
global _is_using_new_api, _is_using_old_api

if _is_using_old_api and _is_using_new_api:
# don't need to do this twice
return

if _is_using_old_api or _is_using_new_api:
msg = (
"Cannot import sire using the mixed API as either the old "
"or new APIs have already been activated."
)
print(msg)

raise ImportError(msg)

# First, bring in the old API
if support_old_module_names:
print("Loading Sire with support for old module names.")
print(
"Note that this can cause problems with classes importing twice."
)
use_old_api()
else:
_is_using_old_api = True

# Now, bring in the new API
_is_using_new_api = True

# call Pythonize on all of the new modules
from . import (
move,
io,
system,
squire,
mm,
ff,
mol,
analysis,
base,
cas,
cluster,
error,
id,
maths,
qt,
stream,
units,
vol,
)

_pythonize_modules(
[
analysis._Analysis,
base._Base,
cas._CAS,
cluster._Cluster,
error._Error,
ff._FF,
id._ID,
io._IO,
maths._Maths,
mm._MM,
mol._Mol,
move._Move,
qt._Qt,
squire._Squire,
stream._Stream,
system._System,
units._Units,
vol._Vol,
],
delete_old=False,
)


def use_new_api():
"""Load Sire using the new (python-style) API. This will be called
automatically when you load any of the new Python modules, so you
shouldn't need to call this yourself.
Internal function to load the new API modules, pythonizing
the function names as we go. If `delete_old` is True, then
the old function names will be deleted. Otherwise, they will
be kept. Keeping the names is only needed for the mixed API.
"""
global _is_using_new_api, _is_using_old_api

# load up the new console - ensure this is done once
from .utils import Console as _Console

_Console._get_console()

if _is_using_new_api:
# already done
return

if _is_using_old_api:
msg = (
"Cannot import sire using the new API as the old API has "
"already been activated. Both APIs cannot be active at "
"the same time."
)
print(msg)

raise ImportError(msg)
global _is_using_new_api

_is_using_new_api = True

Expand Down Expand Up @@ -311,7 +210,8 @@ def use_new_api():
System._System,
Units._Units,
Vol._Vol,
]
],
delete_old=delete_old,
)

try:
Expand Down Expand Up @@ -375,6 +275,74 @@ def use_new_api():
dir(M)


def use_mixed_api(support_old_module_names: bool = False):
"""Load Sire using both the new (python-style) and old APIs. This
is useful for migrating old scripts as a temporary porting option.
You can start writing functions using the new API, safe in the
knowledge that the old API functions will still work.
Do aim to finish your port though, else you will forever have
a duplicated API (e.g. have both X.nAtoms() and X.num_atoms() etc.)
"""
global _is_using_new_api, _is_using_old_api

if _is_using_old_api and _is_using_new_api:
# don't need to do this twice
return

if _is_using_old_api or _is_using_new_api:
msg = (
"Cannot import sire using the mixed API as either the old "
"or new APIs have already been activated."
)
print(msg)

raise ImportError(msg)

# First, bring in the old API
if support_old_module_names:
print("Loading Sire with support for old module names.")
print(
"Note that this can cause problems with classes importing twice."
)
use_old_api()
else:
_is_using_old_api = True

# Now bring in the new API
_load_new_api_modules(delete_old=False)


def use_new_api():
"""Load Sire using the new (python-style) API. This will be called
automatically when you load any of the new Python modules, so you
shouldn't need to call this yourself.
"""
global _is_using_new_api, _is_using_old_api

# load up the new console - ensure this is done once
from .utils import Console as _Console

_Console._get_console()

if _is_using_new_api:
# already done
return

if _is_using_old_api:
msg = (
"Cannot import sire using the new API as the old API has "
"already been activated. Both APIs cannot be active at "
"the same time."
)
print(msg)

raise ImportError(msg)

# Now bring in the new API
_load_new_api_modules(delete_old=True)


def use_old_api():
"""Load Sire using the old (C++-style) API. This is for
compatibility reasons for old code only. This should
Expand Down
29 changes: 18 additions & 11 deletions src/sire/convert/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,12 @@

from .. import use_new_api as _use_new_api

# Imported to ensure that these classes are properly wrapped
from ..maths import Vector as _Vector
from ..cas import LambdaSchedule as _LambdaSchedule

from ..mol import SelectorMol as _SelectorMol

_use_new_api()


def _to_selectormol(obj):
from ..mol import SelectorMol

if hasattr(obj, "molecules"):
return obj.molecules()
elif type(obj) is list:
Expand All @@ -33,9 +29,9 @@ def _to_selectormol(obj):
for o in obj:
mols.append(_to_selectormol(o))

return _SelectorMol(mols)
return SelectorMol(mols)
else:
return _SelectorMol(obj)
return SelectorMol(obj)


def supported_formats():
Expand Down Expand Up @@ -351,6 +347,19 @@ def sire_to_openmm(obj, map=None):
of molecules) to an OpenMM equivalent
"""
# will eventually support System too...
from ..system import System
from ..base import create_map

map = create_map(map)

if System.is_system(obj):
# bring in system-level properties
if not map.specified("space"):
map.set("space", obj.space())

if not map.specified("time"):
map.set("time", obj.time())

obj = _to_selectormol(obj)

try:
Expand All @@ -361,9 +370,7 @@ def sire_to_openmm(obj, map=None):
"'mamba install -c conda-forge openmm'"
)

from ..base import create_map

mols = _sire_to_openmm(obj, map=create_map(map))
mols = _sire_to_openmm(obj, map=map)

return mols

Expand Down
5 changes: 4 additions & 1 deletion src/sire/mol/_dynamics.py
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,10 @@ def __init__(

_add_extra(extras, "cutoff", cutoff)
_add_extra(extras, "cutoff_type", cutoff_type)
_add_extra(extras, "timestep", u(timestep))

if timestep is not None:
_add_extra(extras, "timestep", u(timestep))

_add_extra(extras, "save_frequency", save_frequency)
_add_extra(extras, "constraint", constraint)
_add_extra(extras, "schedule", schedule)
Expand Down

0 comments on commit bcc2acd

Please sign in to comment.