From 9ac44ce815349461050bae916c4c6cb8284ab39e Mon Sep 17 00:00:00 2001 From: m-rauen Date: Tue, 26 Nov 2024 18:34:35 -0300 Subject: [PATCH 1/8] starting to add caching to inertia moment calculation during the simulation --- overreact/coords.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/overreact/coords.py b/overreact/coords.py index ab3525bd..840328d1 100644 --- a/overreact/coords.py +++ b/overreact/coords.py @@ -2,6 +2,7 @@ # TODO(schneiderfelipe): add types to this module from __future__ import annotations +from functools import lru_cache __all__ = ["find_point_group", "symmetry_number"] @@ -1680,7 +1681,7 @@ def gyradius(atommasses, atomcoords, method="iupac"): msg = f"unavailable method: '{method}'" raise ValueError(msg) - +@lru_cache() def inertia(atommasses, atomcoords, align=True): r"""Calculate primary moments and axes from the inertia tensor. From 37ad0e353d768ddf0bd69bc23266e5d1931b20f5 Mon Sep 17 00:00:00 2001 From: m-rauen Date: Tue, 3 Dec 2024 16:44:06 -0300 Subject: [PATCH 2/8] correct caching problem of not handle mutable objects --- overreact/coords.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/overreact/coords.py b/overreact/coords.py index 840328d1..cb54e84f 100644 --- a/overreact/coords.py +++ b/overreact/coords.py @@ -2,7 +2,7 @@ # TODO(schneiderfelipe): add types to this module from __future__ import annotations -from functools import lru_cache +import functools __all__ = ["find_point_group", "symmetry_number"] @@ -1680,8 +1680,22 @@ def gyradius(atommasses, atomcoords, method="iupac"): else: msg = f"unavailable method: '{method}'" raise ValueError(msg) - -@lru_cache() + +def ignore_unhashable(func): + uncached = func.__wrapped__ + attributes = functools.WRAPPER_ASSIGNMENTS + ('cache_info', 'cache_clear') + @functools.wraps(func, assigned=attributes) + def wrapper(*args, **kwargs): + try: + return func(*args, **kwargs) + except TypeError as error: + if 'unhashable type' in str(error): + return uncached(*args, **kwargs) + raise + wrapper.__uncached__ = uncached + return wrapper +@ignore_unhashable +@functools.lru_cache() def inertia(atommasses, atomcoords, align=True): r"""Calculate primary moments and axes from the inertia tensor. From 014b59d84b3882bbc22f762ba2cb43763f3e5bb5 Mon Sep 17 00:00:00 2001 From: m-rauen Date: Tue, 3 Dec 2024 18:16:53 -0300 Subject: [PATCH 3/8] move ignore_unhashable to _misc module + trying to resolve circular import --- overreact/_misc.py | 14 ++++++++++++++ overreact/coords.py | 20 ++++---------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/overreact/_misc.py b/overreact/_misc.py index cacaa5e0..82a3ae44 100644 --- a/overreact/_misc.py +++ b/overreact/_misc.py @@ -6,6 +6,7 @@ from __future__ import annotations import contextlib +import functools from functools import lru_cache as cache import numpy as np @@ -14,6 +15,19 @@ import overreact as rx from overreact import _constants as constants +def ignore_unhashable(func): + uncached = func.__wrapped__ + attributes = functools.WRAPPER_ASSIGNMENTS + ('cache_info', 'cache_clear') + @functools.wraps(func, assigned=attributes) + def wrapper(*args, **kwargs): + try: + return func(*args, **kwargs) + except TypeError as error: + if 'unhashable type' in str(error): + return uncached(*args, **kwargs) + raise + wrapper.__uncached__ = uncached + return wrapper def _find_package(package): """Check if a package exists without importing it. diff --git a/overreact/coords.py b/overreact/coords.py index cb54e84f..9603bb48 100644 --- a/overreact/coords.py +++ b/overreact/coords.py @@ -2,7 +2,7 @@ # TODO(schneiderfelipe): add types to this module from __future__ import annotations -import functools +from functools import lru_cache as cache __all__ = ["find_point_group", "symmetry_number"] @@ -1681,21 +1681,9 @@ def gyradius(atommasses, atomcoords, method="iupac"): msg = f"unavailable method: '{method}'" raise ValueError(msg) -def ignore_unhashable(func): - uncached = func.__wrapped__ - attributes = functools.WRAPPER_ASSIGNMENTS + ('cache_info', 'cache_clear') - @functools.wraps(func, assigned=attributes) - def wrapper(*args, **kwargs): - try: - return func(*args, **kwargs) - except TypeError as error: - if 'unhashable type' in str(error): - return uncached(*args, **kwargs) - raise - wrapper.__uncached__ = uncached - return wrapper -@ignore_unhashable -@functools.lru_cache() + +@rx._misc.ignore_unhashable +@cache() def inertia(atommasses, atomcoords, align=True): r"""Calculate primary moments and axes from the inertia tensor. From 721614799d2ab36fb47b53f348bd02186cb179f7 Mon Sep 17 00:00:00 2001 From: m-rauen Date: Wed, 4 Dec 2024 16:02:10 -0300 Subject: [PATCH 4/8] circular import solved + movem from pkg_resources to importlib --- .gitignore | 1 + overreact/__init__.py | 5 +++-- overreact/_misc.py | 2 ++ overreact/coords.py | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index ad4a1f17..6443b44f 100644 --- a/.gitignore +++ b/.gitignore @@ -174,3 +174,4 @@ poetry.toml pyrightconfig.json # End of https://www.toptal.com/developers/gitignore/api/python +testando/ diff --git a/overreact/__init__.py b/overreact/__init__.py index 347a058a..b77a5b2b 100644 --- a/overreact/__init__.py +++ b/overreact/__init__.py @@ -4,7 +4,8 @@ __docformat__ = "restructuredtext" -import pkg_resources as _pkg_resources +#import pkg_resources as _pkg_resources +from importlib.metadata import version from overreact.api import ( get_enthalpies, @@ -48,7 +49,7 @@ "unparse_reactions", ] -__version__ = _pkg_resources.get_distribution(__name__).version +__version__ = version(__name__) __license__ = "MIT" # I'm too lazy to get it from setup.py... __headline__ = "📈 Create and analyze chemical microkinetic models built from computational chemistry data." diff --git a/overreact/_misc.py b/overreact/_misc.py index 82a3ae44..2cf3ba8d 100644 --- a/overreact/_misc.py +++ b/overreact/_misc.py @@ -16,6 +16,8 @@ from overreact import _constants as constants def ignore_unhashable(func): + """ + """ uncached = func.__wrapped__ attributes = functools.WRAPPER_ASSIGNMENTS + ('cache_info', 'cache_clear') @functools.wraps(func, assigned=attributes) diff --git a/overreact/coords.py b/overreact/coords.py index 9603bb48..6a27dc48 100644 --- a/overreact/coords.py +++ b/overreact/coords.py @@ -18,6 +18,7 @@ import overreact as rx from overreact import _constants as constants +from overreact import _misc as _misc logger = logging.getLogger(__name__) From 184a193ba66de6804d8bd307d5ba4b0383bf1779 Mon Sep 17 00:00:00 2001 From: m-rauen Date: Wed, 4 Dec 2024 16:02:44 -0300 Subject: [PATCH 5/8] updated gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6443b44f..ad4a1f17 100644 --- a/.gitignore +++ b/.gitignore @@ -174,4 +174,3 @@ poetry.toml pyrightconfig.json # End of https://www.toptal.com/developers/gitignore/api/python -testando/ From ddb4846b88a8c8d120cf204ab8af33fcc95b858e Mon Sep 17 00:00:00 2001 From: m-rauen Date: Wed, 4 Dec 2024 18:05:28 -0300 Subject: [PATCH 6/8] change ignore to copy strategy for cache + add docstring --- overreact/_misc.py | 39 +++++++++++++++++++++++---------------- overreact/coords.py | 4 +--- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/overreact/_misc.py b/overreact/_misc.py index 2cf3ba8d..83f5e623 100644 --- a/overreact/_misc.py +++ b/overreact/_misc.py @@ -6,8 +6,8 @@ from __future__ import annotations import contextlib -import functools from functools import lru_cache as cache +from copy import deepcopy import numpy as np from scipy.stats import cauchy, norm @@ -15,22 +15,29 @@ import overreact as rx from overreact import _constants as constants -def ignore_unhashable(func): - """ +def copy_unhashable(maxsize=100000, typed=False): + """Creates a copy of the arrays received by lru_cache and make them hashable, therefore maintaining the arrays to be passed and caching prototypes of those arrays. + + Insipired by: + + + Parameters + ---------- + maxsize : int + typed : bool + If true, function arguments of different types will be cached separately. + + Returns + -------- + function """ - uncached = func.__wrapped__ - attributes = functools.WRAPPER_ASSIGNMENTS + ('cache_info', 'cache_clear') - @functools.wraps(func, assigned=attributes) - def wrapper(*args, **kwargs): - try: - return func(*args, **kwargs) - except TypeError as error: - if 'unhashable type' in str(error): - return uncached(*args, **kwargs) - raise - wrapper.__uncached__ = uncached - return wrapper - + def decorator(func): + cached_func = cache(maxsize=maxsize, typed=typed)(func) + def wrapper(*args, **kwargs): + return deepcopy(cached_func(*args, **kwargs)) + return wrapper + return decorator + def _find_package(package): """Check if a package exists without importing it. diff --git a/overreact/coords.py b/overreact/coords.py index 6a27dc48..3e2f5458 100644 --- a/overreact/coords.py +++ b/overreact/coords.py @@ -2,7 +2,6 @@ # TODO(schneiderfelipe): add types to this module from __future__ import annotations -from functools import lru_cache as cache __all__ = ["find_point_group", "symmetry_number"] @@ -1683,8 +1682,7 @@ def gyradius(atommasses, atomcoords, method="iupac"): raise ValueError(msg) -@rx._misc.ignore_unhashable -@cache() +@rx._misc.copy_unhashable def inertia(atommasses, atomcoords, align=True): r"""Calculate primary moments and axes from the inertia tensor. From edae933e9a2c13b95609a35471ecdb820358bea6 Mon Sep 17 00:00:00 2001 From: m-rauen Date: Wed, 4 Dec 2024 22:12:22 -0300 Subject: [PATCH 7/8] change maxsize of copy_unhashable --- overreact/__init__.py | 1 - overreact/_misc.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/overreact/__init__.py b/overreact/__init__.py index b77a5b2b..921c357a 100644 --- a/overreact/__init__.py +++ b/overreact/__init__.py @@ -4,7 +4,6 @@ __docformat__ = "restructuredtext" -#import pkg_resources as _pkg_resources from importlib.metadata import version from overreact.api import ( diff --git a/overreact/_misc.py b/overreact/_misc.py index 83f5e623..6ae6af71 100644 --- a/overreact/_misc.py +++ b/overreact/_misc.py @@ -15,7 +15,7 @@ import overreact as rx from overreact import _constants as constants -def copy_unhashable(maxsize=100000, typed=False): +def copy_unhashable(maxsize=128, typed=False): """Creates a copy of the arrays received by lru_cache and make them hashable, therefore maintaining the arrays to be passed and caching prototypes of those arrays. Insipired by: From bcce5540f4c87ddfbd87c400c56d9e19f743382b Mon Sep 17 00:00:00 2001 From: m-rauen Date: Mon, 9 Dec 2024 23:37:32 -0300 Subject: [PATCH 8/8] changing hash strategy to eliminate errors --- overreact/_misc.py | 8 ++++++++ overreact/coords.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/overreact/_misc.py b/overreact/_misc.py index 6ae6af71..de823caf 100644 --- a/overreact/_misc.py +++ b/overreact/_misc.py @@ -15,6 +15,14 @@ import overreact as rx from overreact import _constants as constants +def make_hashable(obj): + if isinstance(obj, np.ndarray): + return tuple(obj.ravel()) + elif isinstance(obj, (list, set)): + return tuple(map(make_hashable, obj)) + else: + return obj + def copy_unhashable(maxsize=128, typed=False): """Creates a copy of the arrays received by lru_cache and make them hashable, therefore maintaining the arrays to be passed and caching prototypes of those arrays. diff --git a/overreact/coords.py b/overreact/coords.py index 3e2f5458..2c1467ea 100644 --- a/overreact/coords.py +++ b/overreact/coords.py @@ -1682,7 +1682,7 @@ def gyradius(atommasses, atomcoords, method="iupac"): raise ValueError(msg) -@rx._misc.copy_unhashable +@rx._misc.copy_unhashable() def inertia(atommasses, atomcoords, align=True): r"""Calculate primary moments and axes from the inertia tensor.