mxlpy 0.21.0__py3-none-any.whl → 0.23.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
mxlpy/units.py ADDED
@@ -0,0 +1,133 @@
1
+ """Unit definitions for MxlPy."""
2
+
3
+ from sympy.physics.units import (
4
+ ampere,
5
+ becquerel,
6
+ candela,
7
+ coulomb,
8
+ farad,
9
+ gram,
10
+ gray,
11
+ henry,
12
+ hertz,
13
+ hour,
14
+ joule,
15
+ katal,
16
+ kelvin,
17
+ kilogram,
18
+ liter,
19
+ lux,
20
+ meter,
21
+ micro,
22
+ milli,
23
+ minute,
24
+ mol,
25
+ nano,
26
+ newton,
27
+ ohm,
28
+ pascal,
29
+ pico,
30
+ radian,
31
+ second,
32
+ siemens,
33
+ steradian,
34
+ tesla,
35
+ volt,
36
+ watt,
37
+ weber,
38
+ )
39
+ from sympy.physics.units.quantities import Quantity
40
+
41
+ __all__ = [
42
+ "ampere",
43
+ "becquerel",
44
+ "coulomb",
45
+ "dimensionless",
46
+ "farad",
47
+ "gram",
48
+ "gray",
49
+ "henry",
50
+ "hertz",
51
+ "hour",
52
+ "item",
53
+ "joule",
54
+ "katal",
55
+ "kelvin",
56
+ "liter",
57
+ "lumen",
58
+ "lux",
59
+ "micro",
60
+ "milli",
61
+ "minute",
62
+ "mmol",
63
+ "mmol_g",
64
+ "mmol_s",
65
+ "mol",
66
+ "nano",
67
+ "newton",
68
+ "nmol",
69
+ "ohm",
70
+ "pascal",
71
+ "ppfd",
72
+ "radian",
73
+ "second",
74
+ "siemens",
75
+ "sievert",
76
+ "sqm",
77
+ "tesla",
78
+ "volt",
79
+ "watt",
80
+ "weber",
81
+ ]
82
+
83
+ # time unit
84
+ per_second = 1 / second # type: ignore
85
+ per_minute = 1 / minute # type: ignore
86
+ per_hour = 1 / hour # type: ignore
87
+
88
+
89
+ sqm = meter**2
90
+ cbm = meter**3
91
+
92
+ mol_s = mol / second # type: ignore
93
+ mol_m = mol / minute # type: ignore
94
+ mol_h = mol / hour # type: ignore
95
+ mol_g = mol / gram # type: ignore
96
+
97
+ mmol = mol * milli
98
+ mmol_s = mmol / second
99
+ mmol_m = mmol / minute
100
+ mmol_h = mmol / hour
101
+ mmol_g = mmol / gram
102
+
103
+ mumol = mol * micro
104
+ mumol_s = mumol / second
105
+ mumol_m = mumol / minute
106
+ mumol_h = mumol / hour
107
+ mumol_g = mumol / gram
108
+
109
+ nmol = mol * nano
110
+ nmol_s = nmol / second
111
+ nmol_m = nmol / minute
112
+ nmol_h = nmol / hour
113
+ nmol_g = nmol / gram
114
+
115
+ pmol = mol * pico
116
+ pmol_s = pmol / second
117
+ pmol_m = pmol / minute
118
+ pmol_h = pmol / hour
119
+ pmol_g = pmol / gram
120
+
121
+ ppfd = mumol / sqm / second
122
+
123
+
124
+ # SBML units
125
+ avogadro = 6.02214076e23
126
+ sievert = joule / kilogram # type: ignore
127
+ lumen = candela * steradian # type: ignore
128
+ dimensionless = None
129
+ item = 1 # pseudounit for one thing
130
+
131
+ # Plant units
132
+ mol_chl = Quantity("mol_chl", abbrev="mol_chl")
133
+ mmol_mol_chl = mmol / mol_chl
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mxlpy
3
- Version: 0.21.0
3
+ Version: 0.23.0
4
4
  Summary: A package to build metabolic models
5
5
  Author-email: Marvin van Aalst <marvin.vanaalst@gmail.com>
6
6
  Maintainer-email: Marvin van Aalst <marvin.vanaalst@gmail.com>
@@ -22,6 +22,7 @@ Classifier: Programming Language :: Python :: 3.11
22
22
  Classifier: Topic :: Scientific/Engineering
23
23
  Classifier: Topic :: Software Development
24
24
  Requires-Python: >=3.12
25
+ Requires-Dist: diffrax>=0.7.0
25
26
  Requires-Dist: dill>=0.3.9
26
27
  Requires-Dist: latexify-py>=0.4.4
27
28
  Requires-Dist: lazy-import>=0.2.2
@@ -32,6 +33,7 @@ Requires-Dist: numpy>=2.1.2
32
33
  Requires-Dist: pandas>=2.2.3
33
34
  Requires-Dist: parameteriser>=0.1.0
34
35
  Requires-Dist: pebble>=5.0.7
36
+ Requires-Dist: pysbml>=0.2.0
35
37
  Requires-Dist: python-libsbml>=5.20.4
36
38
  Requires-Dist: salib>=1.5.1
37
39
  Requires-Dist: scipy>=1.14.1
@@ -42,6 +44,7 @@ Requires-Dist: tabulate>=0.9.0
42
44
  Requires-Dist: toml>=0.10.2
43
45
  Requires-Dist: tqdm>=4.66.6
44
46
  Requires-Dist: typing-extensions>=4.12.2
47
+ Requires-Dist: wadler-lindig>=0.1.7
45
48
  Provides-Extra: keras
46
49
  Requires-Dist: keras>=3.9.2; extra == 'keras'
47
50
  Provides-Extra: tensorflow
@@ -0,0 +1,57 @@
1
+ mxlpy/__init__.py,sha256=XQc1WNOxUzRbM8s7hO4p6r7dFsru0BCcedJITawqIo0,4574
2
+ mxlpy/carousel.py,sha256=nYWEdxDd7lm5INfZjpwaEhYqysg9e4EH9Ubcl6bPca8,4721
3
+ mxlpy/compare.py,sha256=o-tUxHJrzzVsQkiKPCFD_4bpqsWrvBMyOPoBQ1Dl420,7746
4
+ mxlpy/distributions.py,sha256=ce6RTqn19YzMMec-u09fSIUA8A92M6rehCuHuXWcX7A,8734
5
+ mxlpy/fit.py,sha256=3hGUqJ2tOOToZLMMaJw5M9b6_UlUJwT_MhUvfPmRBd8,22355
6
+ mxlpy/fns.py,sha256=NLxYwa3ylS7SkISBjw_TgQSKEm7WnkZF9wPigX_ZCAM,13915
7
+ mxlpy/identify.py,sha256=G-Zyr_l-K2mDtIV1xGrQ52QJxoBYqRoNA5RW6GpbNjs,2213
8
+ mxlpy/label_map.py,sha256=PwYanfg07hC0ayyOOP72RFlCQNvhCTbpOhW6kZZ2GUU,17826
9
+ mxlpy/linear_label_map.py,sha256=6Ye6IziWGKkYD_5z3FmTVwnJ2T9SvVGN3U4CfXjXseo,10320
10
+ mxlpy/mc.py,sha256=6n6VAuSVcXinqcWxNJAioMYpBmSAB40WItPloK1vmBM,17017
11
+ mxlpy/mca.py,sha256=IoOHJbjPnAEDqKk64OjFjgRPX5K_aE9D4RrCJ1xFIkw,9457
12
+ mxlpy/model.py,sha256=tAz_Rbe_S1Ho-k_14gBxmE9RMYo2xJUWYkdLYUyMKHg,79072
13
+ mxlpy/parallel.py,sha256=yLQLw5O4vnPVp_Zmtw1UhPWtB3483foimxQB-TwFKPg,5016
14
+ mxlpy/parameterise.py,sha256=IgbvfEnkmaqVq_5GgFjHqApGUN9CJrsVD3Fr7pg9iFA,758
15
+ mxlpy/paths.py,sha256=TK2wO4N9lG-UV1JGfeB64q48JVDbwqIUj63rl55MKuQ,1022
16
+ mxlpy/plot.py,sha256=oZq8NqycdiJwqEm7FVpNTBkjGYgPBEbqDqZxbrvUtDI,32662
17
+ mxlpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ mxlpy/report.py,sha256=v597yzKecgtoNmlNZ_nVhBCa3czNw0tksOK5mLtAQvE,10631
19
+ mxlpy/scan.py,sha256=DI5R_xKEUV28FTXqxYz41lQFkAXHE41R_S-ztHPeCoM,13676
20
+ mxlpy/simulator.py,sha256=NaD0UxvEqiRUp8dZqW4su1Xc9QzHwa9XqGGAIgGV6D0,16559
21
+ mxlpy/types.py,sha256=FpNZT5ZkhFHYSVA1LS7eZ3ljpzK0_fHo5h48nregR6w,31440
22
+ mxlpy/units.py,sha256=4bKXkCYsONUVWRdzV7aVcWFQSA6sxilebgXXFUEKw_c,2091
23
+ mxlpy/experimental/__init__.py,sha256=kZTE-92OErpHzNRqmgSQYH4CGXrogGJ5EL35XGZQ81M,206
24
+ mxlpy/experimental/diff.py,sha256=g5hKvFsEUdEk5OGQ_aQuCxLAnenD_jG4G__EcVfKsx4,9104
25
+ mxlpy/integrators/__init__.py,sha256=TKo2dkJqdW3_n7YrmF6k3kEjr8_kr3-7MDaLu-zFWRg,533
26
+ mxlpy/integrators/int_assimulo.py,sha256=1cvR8cOBdrl_DQs9v0o7wItSG5iyYqwZVh7EO0fg3ro,5021
27
+ mxlpy/integrators/int_diffrax.py,sha256=q_8NZgIZ6T-SRRcI8kSjEb6l-DbXqPv6rjj9KApkQac,3326
28
+ mxlpy/integrators/int_scipy.py,sha256=xKyisVN1jW5hxmVD2K_RpoQ2MwNrMxSGODsAEgEt6_I,4922
29
+ mxlpy/meta/__init__.py,sha256=_Bec5aPJ6YyAkxUXlsQtAy_2VzX0tPGVSj-eGACqrXc,404
30
+ mxlpy/meta/codegen_latex.py,sha256=i4tPvk2-toAYqtf4TynuE9sfUSHUp21AMUgjgFEB0uo,23215
31
+ mxlpy/meta/codegen_model.py,sha256=mRpK7pTPYTIMmJAqno7TA6vg5poSQThGWP43_zHU7as,5124
32
+ mxlpy/meta/codegen_mxlpy.py,sha256=asXGAY0fr5sUSRw7LlBUoFgTkXcJt9M6LZtVqsiF4RU,7869
33
+ mxlpy/meta/source_tools.py,sha256=dqP2dP8OLloBY8pLPuQl2uVB6GfDDn52u8vhPOTei1M,22302
34
+ mxlpy/meta/sympy_tools.py,sha256=XaRXdyXiiiOHBXatxoRTRKwy7BaM9I0lL6PE5HP33wE,3016
35
+ mxlpy/nn/__init__.py,sha256=Qjr-ERsY2lbD75sFBOhCUwEasQDSJKcpBn_kReLZ6oA,633
36
+ mxlpy/nn/_keras.py,sha256=-5zjHRu8OjSiZeuBSIZFyB63uBsNNH5o9y4kBcPnhx8,2263
37
+ mxlpy/nn/_torch.py,sha256=GUJmLU282VU4O-fs3Sz90SEaAnfuXN2MPlBr_tHmvn4,5775
38
+ mxlpy/npe/__init__.py,sha256=hBHCUD2JYDBBGS2kTY8mTCfWB3u1R7m5l--wUupZt6o,1270
39
+ mxlpy/npe/_keras.py,sha256=ytvXMPK9KUCGOzTQm08_SgafiMb-MOIUdZQV7JjAO40,9721
40
+ mxlpy/npe/_torch.py,sha256=v3joh6lFJJxvYJj--wzmKXL9UMTaIN3h6hPNq0uX9NU,11250
41
+ mxlpy/sbml/__init__.py,sha256=Mt97CddpLi3wIrA1b_5cagLmDdNxAVF_S7QV57Pzw8s,226
42
+ mxlpy/sbml/_data.py,sha256=yYli7ZQ1_pnH9kt5EmcuHM0moQoa43rrFVdrseXlG0o,1136
43
+ mxlpy/sbml/_export.py,sha256=0R34btB5COKD1gsWisdlWdEbJ-BUrjb78s6sWnm5Ph4,20945
44
+ mxlpy/sbml/_import.py,sha256=_4MR54YyVkIh9eVAiSMd7yijhHC_ds-3v7M_C4Zn8BY,3565
45
+ mxlpy/sbml/_name_conversion.py,sha256=93muW47M7qJoE227HKHmThWpPeWsXDN9eM8cRH2pqPs,1340
46
+ mxlpy/surrogates/__init__.py,sha256=cz9qr0ToYSutIK45IvKrMe1mPP7Lj0I_V0HYGixfpZU,916
47
+ mxlpy/surrogates/_keras.py,sha256=r2pR3iTJOaMqtATbsCm5CF94TYG9b-9cKljc8kMOplQ,3852
48
+ mxlpy/surrogates/_poly.py,sha256=z2g3JTdVyQJ8dIiXP4BOun_yMZOrlYpPNvQ0wmFYDTk,3672
49
+ mxlpy/surrogates/_qss.py,sha256=9w-hPPhdcwybkyaSX0sIfYfvcKu1U5j4HHj4SlgZcYQ,723
50
+ mxlpy/surrogates/_torch.py,sha256=gU0secuRBYgewhNqZmSo6_Xf804dSzwWwIYmdKA7y60,6389
51
+ mxlpy/symbolic/__init__.py,sha256=_vM5YM5I6OH0QDbFt9uGYKO8Z5Vly0wbGuvUScVrPRU,258
52
+ mxlpy/symbolic/strikepy.py,sha256=tzo3uvPpXLDex09hWTuitVzuTNwbgl7jWGjD8g6a8iI,20033
53
+ mxlpy/symbolic/symbolic_model.py,sha256=cKfWoktvFmXjuo8egE7gXKrKBq2iBUiy_BcIKIvvz8A,3026
54
+ mxlpy-0.23.0.dist-info/METADATA,sha256=80ODNl3NCffUmuu_mJmvUmld7uNm390vMtlhNx2Soes,4696
55
+ mxlpy-0.23.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
56
+ mxlpy-0.23.0.dist-info/licenses/LICENSE,sha256=lHX9Eu70g3Iv1aOxXTWNHa3vq9vaVYSPQx4jOLYmDpw,1096
57
+ mxlpy-0.23.0.dist-info/RECORD,,
@@ -1,112 +0,0 @@
1
- """Generate mxlpy code from a model."""
2
-
3
- from __future__ import annotations
4
-
5
- import warnings
6
- from typing import TYPE_CHECKING
7
-
8
- import sympy
9
-
10
- from mxlpy.meta.source_tools import fn_to_sympy, sympy_to_fn
11
- from mxlpy.types import Derived
12
-
13
- if TYPE_CHECKING:
14
- from mxlpy.model import Model
15
-
16
- __all__ = [
17
- "generate_mxlpy_code",
18
- ]
19
-
20
-
21
- def _list_of_symbols(args: list[str]) -> list[sympy.Symbol | sympy.Expr]:
22
- return [sympy.Symbol(arg) for arg in args]
23
-
24
-
25
- def generate_mxlpy_code(model: Model) -> str:
26
- """Generate a mxlpy model from a model."""
27
- functions = {}
28
-
29
- # Variables and parameters
30
- variables = model.variables
31
- parameters = model.parameters
32
-
33
- # Derived
34
- derived_source = []
35
- for k, der in model.derived.items():
36
- fn = der.fn
37
- fn_name = fn.__name__
38
- functions[fn_name] = (
39
- fn_to_sympy(fn, model_args=_list_of_symbols(der.args)),
40
- der.args,
41
- )
42
-
43
- derived_source.append(
44
- f""" .add_derived(
45
- "{k}",
46
- fn={fn_name},
47
- args={der.args},
48
- )"""
49
- )
50
-
51
- # Reactions
52
- reactions_source = []
53
- for k, rxn in model.reactions.items():
54
- fn = rxn.fn
55
- fn_name = fn.__name__
56
- functions[fn_name] = (
57
- fn_to_sympy(fn, model_args=_list_of_symbols(rxn.args)),
58
- rxn.args,
59
- )
60
- stoichiometry: list[str] = []
61
- for var, stoich in rxn.stoichiometry.items():
62
- if isinstance(stoich, Derived):
63
- functions[fn_name] = (
64
- fn_to_sympy(fn, model_args=_list_of_symbols(stoich.args)),
65
- rxn.args,
66
- )
67
- args = ", ".join(f'"{k}"' for k in stoich.args)
68
- stoich = ( # noqa: PLW2901
69
- f"""Derived(fn={fn.__name__}, args=[{args}])"""
70
- )
71
- stoichiometry.append(f""""{var}": {stoich}""")
72
-
73
- reactions_source.append(
74
- f""" .add_reaction(
75
- "{k}",
76
- fn={fn_name},
77
- args={rxn.args},
78
- stoichiometry={{{",".join(stoichiometry)}}},
79
- )"""
80
- )
81
-
82
- # Surrogates
83
- if len(model._surrogates) > 0: # noqa: SLF001
84
- warnings.warn(
85
- "Generating code for Surrogates not yet supported.",
86
- stacklevel=1,
87
- )
88
-
89
- # Combine all the sources
90
- functions_source = "\n\n".join(
91
- sympy_to_fn(fn_name=name, args=args, expr=expr)
92
- for name, (expr, args) in functions.items()
93
- )
94
- source = [
95
- "from mxlpy import Model\n",
96
- functions_source,
97
- "def create_model() -> Model:",
98
- " return (",
99
- " Model()",
100
- ]
101
- if len(parameters) > 0:
102
- source.append(f" .add_parameters({parameters})")
103
- if len(variables) > 0:
104
- source.append(f" .add_variables({variables})")
105
- if len(derived_source) > 0:
106
- source.append("\n".join(derived_source))
107
- if len(reactions_source) > 0:
108
- source.append("\n".join(reactions_source))
109
-
110
- source.append(" )")
111
-
112
- return "\n".join(source)
mxlpy/meta/codegen_py.py DELETED
@@ -1,115 +0,0 @@
1
- """Module to export models as code."""
2
-
3
- from __future__ import annotations
4
-
5
- import warnings
6
- from typing import TYPE_CHECKING
7
-
8
- import sympy
9
-
10
- from mxlpy.meta.source_tools import fn_to_sympy, sympy_to_inline
11
- from mxlpy.types import Derived
12
-
13
- if TYPE_CHECKING:
14
- from collections.abc import Callable, Generator, Iterable, Iterator
15
-
16
- from mxlpy.model import Model
17
-
18
- __all__ = [
19
- "generate_model_code_py",
20
- ]
21
-
22
-
23
- def _conditional_join[T](
24
- iterable: Iterable[T],
25
- question: Callable[[T], bool],
26
- true_pat: str,
27
- false_pat: str,
28
- ) -> str:
29
- """Join an iterable, applying a pattern to each element based on a condition."""
30
-
31
- def inner(it: Iterator[T]) -> Generator[str, None, None]:
32
- yield str(next(it))
33
- while True:
34
- try:
35
- el = next(it)
36
- if question(el):
37
- yield f"{true_pat}{el}"
38
- else:
39
- yield f"{false_pat}{el}"
40
- except StopIteration:
41
- break
42
-
43
- return "".join(inner(iter(iterable)))
44
-
45
-
46
- def _list_of_symbols(args: list[str]) -> list[sympy.Symbol | sympy.Expr]:
47
- return [sympy.Symbol(arg) for arg in args]
48
-
49
-
50
- # FIXME: generate from SymbolicModel, should be easier?
51
- def generate_model_code_py(model: Model) -> str:
52
- """Transform the model into a single function, inlining the function calls."""
53
- source = [
54
- "from collections.abc import Iterable\n",
55
- "from mxlpy.types import Float\n",
56
- "def model(t: Float, variables: Float) -> Iterable[Float]:",
57
- ]
58
-
59
- # Variables
60
- variables = model.variables
61
- if len(variables) > 0:
62
- source.append(" {} = variables".format(", ".join(variables)))
63
-
64
- # Parameters
65
- parameters = model.parameters
66
- if len(parameters) > 0:
67
- source.append("\n".join(f" {k} = {v}" for k, v in model.parameters.items()))
68
-
69
- # Derived
70
- for name, derived in model.derived.items():
71
- expr = fn_to_sympy(derived.fn, model_args=_list_of_symbols(derived.args))
72
- source.append(f" {name} = {sympy_to_inline(expr)}")
73
-
74
- # Reactions
75
- for name, rxn in model.reactions.items():
76
- expr = fn_to_sympy(rxn.fn, model_args=_list_of_symbols(rxn.args))
77
- source.append(f" {name} = {sympy_to_inline(expr)}")
78
-
79
- # Stoichiometries; FIXME: do this with sympy instead as well?
80
- stoich_srcs = {}
81
- for rxn_name, rxn in model.reactions.items():
82
- for i, (cpd_name, factor) in enumerate(rxn.stoichiometry.items()):
83
- if isinstance(factor, Derived):
84
- expr = fn_to_sympy(factor.fn, model_args=_list_of_symbols(factor.args))
85
- src = f"{sympy_to_inline(expr)} * {rxn_name}"
86
- elif factor == 1:
87
- src = rxn_name
88
- elif factor == -1:
89
- src = f"-{rxn_name}" if i == 0 else f"- {rxn_name}"
90
- else:
91
- src = f"{factor} * {rxn_name}"
92
- stoich_srcs.setdefault(cpd_name, []).append(src)
93
- for variable, stoich in stoich_srcs.items():
94
- source.append(
95
- f" d{variable}dt = {_conditional_join(stoich, lambda x: x.startswith('-'), ' ', ' + ')}"
96
- )
97
-
98
- # Surrogates
99
- if len(model._surrogates) > 0: # noqa: SLF001
100
- warnings.warn(
101
- "Generating code for Surrogates not yet supported.",
102
- stacklevel=1,
103
- )
104
-
105
- # Return
106
- if len(variables) > 0:
107
- source.append(
108
- " return {}".format(
109
- ", ".join(f"d{i}dt" for i in variables),
110
- ),
111
- )
112
- else:
113
- source.append(" return ()")
114
-
115
- return "\n".join(source)