modelbase2 0.1.79__py3-none-any.whl → 0.3.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.
Files changed (59) hide show
  1. modelbase2/__init__.py +148 -25
  2. modelbase2/distributions.py +336 -0
  3. modelbase2/experimental/__init__.py +17 -0
  4. modelbase2/experimental/codegen.py +239 -0
  5. modelbase2/experimental/diff.py +227 -0
  6. modelbase2/experimental/notes.md +4 -0
  7. modelbase2/experimental/tex.py +521 -0
  8. modelbase2/fit.py +284 -0
  9. modelbase2/fns.py +185 -0
  10. modelbase2/integrators/__init__.py +19 -0
  11. modelbase2/integrators/int_assimulo.py +146 -0
  12. modelbase2/integrators/int_scipy.py +147 -0
  13. modelbase2/label_map.py +610 -0
  14. modelbase2/linear_label_map.py +301 -0
  15. modelbase2/mc.py +548 -0
  16. modelbase2/mca.py +280 -0
  17. modelbase2/model.py +1621 -0
  18. modelbase2/nnarchitectures.py +128 -0
  19. modelbase2/npe.py +271 -0
  20. modelbase2/parallel.py +171 -0
  21. modelbase2/parameterise.py +28 -0
  22. modelbase2/paths.py +36 -0
  23. modelbase2/plot.py +832 -0
  24. modelbase2/sbml/__init__.py +14 -0
  25. modelbase2/sbml/_data.py +77 -0
  26. modelbase2/sbml/_export.py +656 -0
  27. modelbase2/sbml/_import.py +585 -0
  28. modelbase2/sbml/_mathml.py +691 -0
  29. modelbase2/sbml/_name_conversion.py +52 -0
  30. modelbase2/sbml/_unit_conversion.py +74 -0
  31. modelbase2/scan.py +616 -0
  32. modelbase2/scope.py +96 -0
  33. modelbase2/simulator.py +635 -0
  34. modelbase2/surrogates/__init__.py +31 -0
  35. modelbase2/surrogates/_poly.py +91 -0
  36. modelbase2/surrogates/_torch.py +191 -0
  37. modelbase2/surrogates.py +316 -0
  38. modelbase2/types.py +352 -11
  39. modelbase2-0.3.0.dist-info/METADATA +93 -0
  40. modelbase2-0.3.0.dist-info/RECORD +43 -0
  41. {modelbase2-0.1.79.dist-info → modelbase2-0.3.0.dist-info}/WHEEL +1 -1
  42. modelbase2/core/__init__.py +0 -29
  43. modelbase2/core/algebraic_module_container.py +0 -130
  44. modelbase2/core/constant_container.py +0 -113
  45. modelbase2/core/data.py +0 -109
  46. modelbase2/core/name_container.py +0 -29
  47. modelbase2/core/reaction_container.py +0 -115
  48. modelbase2/core/utils.py +0 -28
  49. modelbase2/core/variable_container.py +0 -24
  50. modelbase2/ode/__init__.py +0 -13
  51. modelbase2/ode/integrator.py +0 -80
  52. modelbase2/ode/mca.py +0 -270
  53. modelbase2/ode/model.py +0 -470
  54. modelbase2/ode/simulator.py +0 -153
  55. modelbase2/utils/__init__.py +0 -0
  56. modelbase2/utils/plotting.py +0 -372
  57. modelbase2-0.1.79.dist-info/METADATA +0 -44
  58. modelbase2-0.1.79.dist-info/RECORD +0 -22
  59. {modelbase2-0.1.79.dist-info → modelbase2-0.3.0.dist-info/licenses}/LICENSE +0 -0
modelbase2/types.py CHANGED
@@ -1,20 +1,361 @@
1
+ """Types Module.
2
+
3
+ This module provides type definitions and utility types for use throughout the project.
4
+ It includes type aliases for arrays, numbers, and callable functions, as well as re-exports
5
+ of common types from standard libraries.
6
+
7
+ Classes:
8
+ DerivedFn: Callable type for derived functions.
9
+ Array: Type alias for numpy arrays of float64.
10
+ Number: Type alias for float, list of floats, or numpy arrays.
11
+ Param: Type alias for parameter specifications.
12
+ RetType: Type alias for return types.
13
+ Axes: Type alias for numpy arrays of matplotlib axes.
14
+ ArrayLike: Type alias for numpy arrays or lists of floats.
15
+ """
16
+
1
17
  from __future__ import annotations
2
18
 
19
+ from abc import abstractmethod
20
+ from dataclasses import dataclass, field
21
+
22
+ import pandas as pd
23
+
3
24
  __all__ = [
25
+ "AbstractSurrogate",
4
26
  "Array",
5
- "Axes",
6
- "DataFrame",
7
- "Figure",
8
- "Series",
27
+ "ArrayLike",
28
+ "Derived",
29
+ "Float",
30
+ "IntegratorProtocol",
31
+ "McSteadyStates",
32
+ "MockSurrogate",
33
+ "Param",
34
+ "ProtocolByPars",
35
+ "RateFn",
36
+ "Reaction",
37
+ "Readout",
38
+ "ResponseCoefficients",
39
+ "ResponseCoefficientsByPars",
40
+ "RetType",
41
+ "SteadyStates",
42
+ "TimeCourseByPars",
43
+ "unwrap",
44
+ "unwrap2",
9
45
  ]
10
46
 
47
+ # Re-exporting some types here, because their imports have
48
+ # changed between Python versions and I have no interest in
49
+ # fixing it in every file
50
+ from collections.abc import Callable, Iterator, Mapping
51
+ from typing import TYPE_CHECKING, Any, ParamSpec, Protocol, TypeVar, cast
52
+
11
53
  import numpy as np
12
54
  import numpy.typing as npt
13
- import pandas as pd
14
- from matplotlib.axes import Axes
15
- from matplotlib.figure import Figure
16
- from typing_extensions import TypeAlias
55
+ from numpy.typing import NDArray
56
+
57
+ type Float = npt.NDArray[np.floating[Any]] | float
58
+ type RateFn = Callable[..., Float]
59
+ type Array = NDArray[np.floating[Any]]
60
+ type ArrayLike = NDArray[np.floating[Any]] | list[float]
61
+
62
+
63
+ Param = ParamSpec("Param")
64
+ RetType = TypeVar("RetType")
65
+
66
+
67
+ if TYPE_CHECKING:
68
+ from modelbase2.model import Model
69
+
70
+
71
+ def unwrap[T](el: T | None) -> T:
72
+ """Unwraps an optional value, raising an error if the value is None.
73
+
74
+ Args:
75
+ el: The value to unwrap. It can be of type T or None.
76
+
77
+ Returns:
78
+ The unwrapped value if it is not None.
79
+
80
+ Raises:
81
+ ValueError: If the provided value is None.
82
+
83
+ """
84
+ if el is None:
85
+ msg = "Unexpected None"
86
+ raise ValueError(msg)
87
+ return el
88
+
89
+
90
+ def unwrap2[T1, T2](tpl: tuple[T1 | None, T2 | None]) -> tuple[T1, T2]:
91
+ """Unwraps a tuple of optional values, raising an error if either of them is None.
92
+
93
+ Args:
94
+ tpl: The value to unwrap.
95
+
96
+ Returns:
97
+ The unwrapped values if it is not None.
98
+
99
+ Raises:
100
+ ValueError: If the provided value is None.
101
+
102
+ """
103
+ a, b = tpl
104
+ if a is None or b is None:
105
+ msg = "Unexpected None"
106
+ raise ValueError(msg)
107
+ return a, b
108
+
109
+
110
+ class IntegratorProtocol(Protocol):
111
+ """Protocol for numerical integrators."""
112
+
113
+ def __init__(
114
+ self,
115
+ rhs: Callable,
116
+ y0: ArrayLike,
117
+ ) -> None:
118
+ """Initialise the integrator."""
119
+ ...
120
+
121
+ def reset(self) -> None:
122
+ """Reset the integrator."""
123
+ ...
124
+
125
+ def integrate(
126
+ self,
127
+ *,
128
+ t_end: float,
129
+ steps: int | None = None,
130
+ ) -> tuple[ArrayLike | None, ArrayLike | None]:
131
+ """Integrate the system."""
132
+ ...
133
+
134
+ def integrate_time_course(
135
+ self, *, time_points: ArrayLike
136
+ ) -> tuple[ArrayLike | None, ArrayLike | None]:
137
+ """Integrate the system over a time course."""
138
+ ...
139
+
140
+ def integrate_to_steady_state(
141
+ self,
142
+ *,
143
+ tolerance: float,
144
+ rel_norm: bool,
145
+ ) -> tuple[float | None, ArrayLike | None]:
146
+ """Integrate the system to steady state."""
147
+ ...
148
+
149
+
150
+ @dataclass(slots=True)
151
+ class Derived:
152
+ """Container for a derived value."""
153
+
154
+ fn: RateFn
155
+ args: list[str]
156
+ math: str | None = None
157
+
158
+
159
+ @dataclass(slots=True)
160
+ class Readout:
161
+ """Container for a readout."""
162
+
163
+ fn: RateFn
164
+ args: list[str]
165
+
166
+
167
+ @dataclass(slots=True)
168
+ class Reaction:
169
+ """Container for a reaction."""
170
+
171
+ fn: RateFn
172
+ stoichiometry: Mapping[str, float | Derived]
173
+ args: list[str]
174
+ math: str | None = None
175
+
176
+ def get_modifiers(self, model: Model) -> list[str]:
177
+ """Get the modifiers of the reaction."""
178
+ include = set(model.variables)
179
+ exclude = set(self.stoichiometry)
180
+
181
+ return [k for k in self.args if k in include and k not in exclude]
182
+
183
+
184
+ @dataclass(slots=True)
185
+ class ResponseCoefficients:
186
+ """Container for response coefficients."""
187
+
188
+ concs: pd.DataFrame
189
+ fluxes: pd.DataFrame
190
+
191
+ def __iter__(self) -> Iterator[pd.DataFrame]:
192
+ """Iterate over the concentration and flux response coefficients."""
193
+ return iter((self.concs, self.fluxes))
194
+
195
+ @property
196
+ def results(self) -> pd.DataFrame:
197
+ """Return the response coefficients as a DataFrame."""
198
+ return pd.concat((self.concs, self.fluxes), axis=1)
199
+
200
+
201
+ @dataclass(slots=True)
202
+ class ResponseCoefficientsByPars:
203
+ """Container for response coefficients by parameter."""
204
+
205
+ concs: pd.DataFrame
206
+ fluxes: pd.DataFrame
207
+ parameters: pd.DataFrame
208
+
209
+ def __iter__(self) -> Iterator[pd.DataFrame]:
210
+ """Iterate over the concentration and flux response coefficients."""
211
+ return iter((self.concs, self.fluxes))
212
+
213
+ @property
214
+ def results(self) -> pd.DataFrame:
215
+ """Return the response coefficients as a DataFrame."""
216
+ return pd.concat((self.concs, self.fluxes), axis=1)
217
+
218
+
219
+ @dataclass(slots=True)
220
+ class SteadyStates:
221
+ """Container for steady states."""
222
+
223
+ concs: pd.DataFrame
224
+ fluxes: pd.DataFrame
225
+ parameters: pd.DataFrame
226
+
227
+ def __iter__(self) -> Iterator[pd.DataFrame]:
228
+ """Iterate over the concentration and flux steady states."""
229
+ return iter((self.concs, self.fluxes))
230
+
231
+ @property
232
+ def results(self) -> pd.DataFrame:
233
+ """Return the steady states as a DataFrame."""
234
+ return pd.concat((self.concs, self.fluxes), axis=1)
235
+
236
+
237
+ @dataclass(slots=True)
238
+ class McSteadyStates:
239
+ """Container for Monte Carlo steady states."""
240
+
241
+ concs: pd.DataFrame
242
+ fluxes: pd.DataFrame
243
+ parameters: pd.DataFrame
244
+ mc_parameters: pd.DataFrame
245
+
246
+ def __iter__(self) -> Iterator[pd.DataFrame]:
247
+ """Iterate over the concentration and flux steady states."""
248
+ return iter((self.concs, self.fluxes))
249
+
250
+ @property
251
+ def results(self) -> pd.DataFrame:
252
+ """Return the steady states as a DataFrame."""
253
+ return pd.concat((self.concs, self.fluxes), axis=1)
254
+
255
+
256
+ @dataclass(slots=True)
257
+ class TimeCourseByPars:
258
+ """Container for time courses by parameter."""
259
+
260
+ concs: pd.DataFrame
261
+ fluxes: pd.DataFrame
262
+ parameters: pd.DataFrame
263
+
264
+ def __iter__(self) -> Iterator[pd.DataFrame]:
265
+ """Iterate over the concentration and flux time courses."""
266
+ return iter((self.concs, self.fluxes))
267
+
268
+ @property
269
+ def results(self) -> pd.DataFrame:
270
+ """Return the time courses as a DataFrame."""
271
+ return pd.concat((self.concs, self.fluxes), axis=1)
272
+
273
+ def get_by_name(self, name: str) -> pd.DataFrame:
274
+ """Get time courses by name."""
275
+ return self.results[name].unstack().T
276
+
277
+ def get_agg_per_time(self, agg: str | Callable) -> pd.DataFrame:
278
+ """Get aggregated time courses."""
279
+ mean = cast(pd.DataFrame, self.results.unstack(level=1).agg(agg, axis=0))
280
+ return cast(pd.DataFrame, mean.unstack().T)
281
+
282
+ def get_agg_per_run(self, agg: str | Callable) -> pd.DataFrame:
283
+ """Get aggregated time courses."""
284
+ mean = cast(pd.DataFrame, self.results.unstack(level=0).agg(agg, axis=0))
285
+ return cast(pd.DataFrame, mean.unstack().T)
286
+
287
+
288
+ @dataclass(slots=True)
289
+ class ProtocolByPars:
290
+ """Container for protocols by parameter."""
291
+
292
+ concs: pd.DataFrame
293
+ fluxes: pd.DataFrame
294
+ parameters: pd.DataFrame
295
+ protocol: pd.DataFrame
296
+
297
+ def __iter__(self) -> Iterator[pd.DataFrame]:
298
+ """Iterate over the concentration and flux protocols."""
299
+ return iter((self.concs, self.fluxes))
300
+
301
+ @property
302
+ def results(self) -> pd.DataFrame:
303
+ """Return the protocols as a DataFrame."""
304
+ return pd.concat((self.concs, self.fluxes), axis=1)
305
+
306
+ def get_by_name(self, name: str) -> pd.DataFrame:
307
+ """Get concentration or flux by name."""
308
+ return self.results[name].unstack().T
309
+
310
+ def get_agg_per_time(self, agg: str | Callable) -> pd.DataFrame:
311
+ """Get aggregated concentration or flux."""
312
+ mean = cast(pd.DataFrame, self.results.unstack(level=1).agg(agg, axis=0))
313
+ return cast(pd.DataFrame, mean.unstack().T)
314
+
315
+ def get_agg_per_run(self, agg: str | Callable) -> pd.DataFrame:
316
+ """Get aggregated concentration or flux."""
317
+ mean = cast(pd.DataFrame, self.results.unstack(level=0).agg(agg, axis=0))
318
+ return cast(pd.DataFrame, mean.unstack().T)
319
+
320
+
321
+ @dataclass(kw_only=True)
322
+ class AbstractSurrogate:
323
+ """Abstract base class for surrogate models.
324
+
325
+ Attributes:
326
+ inputs: List of input variable names.
327
+ stoichiometries: Dictionary mapping reaction names to stoichiometries.
328
+
329
+ Methods:
330
+ predict: Abstract method to predict outputs based on input data.
331
+
332
+ """
333
+
334
+ args: list[str] = field(default_factory=list)
335
+ stoichiometries: dict[str, dict[str, float]] = field(default_factory=dict)
336
+
337
+ @abstractmethod
338
+ def predict_raw(self, y: np.ndarray) -> np.ndarray:
339
+ """Predict outputs based on input data."""
340
+
341
+ def predict(self, y: np.ndarray) -> dict[str, float]:
342
+ """Predict outputs based on input data."""
343
+ return dict(
344
+ zip(
345
+ self.stoichiometries,
346
+ self.predict_raw(y),
347
+ strict=True,
348
+ )
349
+ )
350
+
351
+
352
+ @dataclass(kw_only=True)
353
+ class MockSurrogate(AbstractSurrogate):
354
+ """Mock surrogate model for testing purposes."""
17
355
 
18
- Array: TypeAlias = npt.NDArray[np.float64]
19
- Series: TypeAlias = pd.Series
20
- DataFrame: TypeAlias = pd.DataFrame
356
+ def predict_raw(
357
+ self,
358
+ y: np.ndarray,
359
+ ) -> np.ndarray:
360
+ """Predict outputs based on input data."""
361
+ return y
@@ -0,0 +1,93 @@
1
+ Metadata-Version: 2.4
2
+ Name: modelbase2
3
+ Version: 0.3.0
4
+ Summary: A package to build metabolic models
5
+ Author-email: Marvin van Aalst <marvin.vanaalst@gmail.com>
6
+ Maintainer-email: Marvin van Aalst <marvin.vanaalst@gmail.com>
7
+ License-Expression: GPL-3.0-or-later
8
+ License-File: LICENSE
9
+ Keywords: metabolic,modelling,ode
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Operating System :: POSIX
19
+ Classifier: Operating System :: Unix
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Topic :: Scientific/Engineering
23
+ Classifier: Topic :: Software Development
24
+ Requires-Python: >=3.12
25
+ Requires-Dist: dill>=0.3.9
26
+ Requires-Dist: latexify-py>=0.4.4
27
+ Requires-Dist: matplotlib>=3.9.2
28
+ Requires-Dist: more-itertools>=10.5.0
29
+ Requires-Dist: numpy>=2.1.2
30
+ Requires-Dist: pandas>=2.2.3
31
+ Requires-Dist: parameteriser>=0.1.0
32
+ Requires-Dist: pebble>=5.0.7
33
+ Requires-Dist: python-libsbml>=5.20.4
34
+ Requires-Dist: scipy>=1.14.1
35
+ Requires-Dist: seaborn>=0.13.2
36
+ Requires-Dist: sympy>=1.13.1
37
+ Requires-Dist: tabulate>=0.9.0
38
+ Requires-Dist: tqdm>=4.66.6
39
+ Requires-Dist: typing-extensions>=4.12.2
40
+ Provides-Extra: dev
41
+ Requires-Dist: coverage>=7.6.4; extra == 'dev'
42
+ Requires-Dist: jupyter>=1.1.1; extra == 'dev'
43
+ Requires-Dist: mkdocs-jupyter>=0.25.1; extra == 'dev'
44
+ Requires-Dist: mkdocs-material>=9.5.42; extra == 'dev'
45
+ Requires-Dist: mkdocs>=1.6.1; extra == 'dev'
46
+ Requires-Dist: mypy>=1.13.0; extra == 'dev'
47
+ Requires-Dist: pre-commit>=4.0.1; extra == 'dev'
48
+ Requires-Dist: pyright>=1.1.387; extra == 'dev'
49
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
50
+ Requires-Dist: pytest>=8.3.3; extra == 'dev'
51
+ Requires-Dist: qtbmodels<0.2,>=0.1.0; extra == 'dev'
52
+ Requires-Dist: requests>=2.32.3; extra == 'dev'
53
+ Requires-Dist: ruff>=0.7.1; extra == 'dev'
54
+ Requires-Dist: ssort>=0.13.0; extra == 'dev'
55
+ Requires-Dist: toml-sort<0.24,>=0.23.1; extra == 'dev'
56
+ Provides-Extra: torch
57
+ Requires-Dist: torch>=2.5.1; extra == 'torch'
58
+ Description-Content-Type: text/markdown
59
+
60
+ # modelbase
61
+
62
+ ## Installation
63
+
64
+ You can install modelbase using pip: `pip install modelbase2`
65
+
66
+ If you want access to the sundials solver suite via the [assimulo](https://jmodelica.org/assimulo/) package, we recommend setting up a virtual environment via [pixi](https://pixi.sh/) or [mamba / conda](https://mamba.readthedocs.io/en/latest/) using the [conda-forge](https://conda-forge.org/) channel.
67
+
68
+ ```bash
69
+ pixi init
70
+ pixi add python assimulo
71
+ pixi add --pypi modelbase2
72
+ ```
73
+
74
+
75
+ ## Development setup
76
+
77
+ You have two choices here, using `uv` (pypi-only) or using `pixi` (conda-forge, including assimulo)
78
+
79
+ ### uv
80
+
81
+ - Install `uv` as described in [the docs](https://docs.astral.sh/uv/getting-started/installation/).
82
+ - Run `uv sync --extra dev --extra torch` to install dependencies locally
83
+
84
+ ### pixi
85
+
86
+ - Install `pixi` as described in [the docs](https://pixi.sh/latest/#installation)
87
+ - Run `pixi install --frozen`
88
+
89
+
90
+ ## Notes
91
+
92
+ - `uv add $package`
93
+ - `uv add --optional dev $package`
@@ -0,0 +1,43 @@
1
+ modelbase2/__init__.py,sha256=ArYJZoCTulkjFctJzxk7c9CDBXYRl2J9_LXr1EORilk,4048
2
+ modelbase2/distributions.py,sha256=biNi8bUdWNxtUWFF4A1HaPcaDYtjdi-FkBF0OmATD3c,8688
3
+ modelbase2/fit.py,sha256=kCuwsuUs9DSRyeQXmP6RSclGGMVL1Q7XD3KLhu073yo,8010
4
+ modelbase2/fns.py,sha256=8JtIzPk3DAnNHz3LoJ1ukLFTjPNO1rNCeZ7VnRmJY2o,4503
5
+ modelbase2/label_map.py,sha256=LUwcOHQWiGfBGV5XUmPM_SOwM9IyDVcQVJ11DPfVpAo,17774
6
+ modelbase2/linear_label_map.py,sha256=gA8CHxcehgtI6ovwZ9qNUPDvxfqbO1J1kBC_mltD4TY,10225
7
+ modelbase2/mc.py,sha256=zlDL7e_udpIMRhSjfFJo5AwkigD0B_3H2rQxyelBuzI,16285
8
+ modelbase2/mca.py,sha256=nMS2VnzR2VEujCFUaj9WL82CNd-oxTb3jCHP8IlJvxA,8845
9
+ modelbase2/model.py,sha256=SJloqNi8C5oSrIyknMkXfPFDBHPW-ybrT_F9nsbREzQ,53854
10
+ modelbase2/nnarchitectures.py,sha256=OA1X4UHrn7gsLuuqxK6Dhv5aiKnQflhHezYCUV-NuO8,4012
11
+ modelbase2/npe.py,sha256=PJO5OiUfaeklkk9HnQ3-uJ1GLsZjE_k5MDA2tM-xhV0,8591
12
+ modelbase2/parallel.py,sha256=kX4Td5YoovDwZp6kX_3cfO6QtHSS9ieJ0bMZiKs3Xv8,5002
13
+ modelbase2/parameterise.py,sha256=7VrYxrQv0visraqUthWSnWfx-cxh2evlXbszIY5031U,690
14
+ modelbase2/paths.py,sha256=uatKXDa79uniUB2Z3dr8eBJVuUPXDI-o_bf-DqPKq1Y,1039
15
+ modelbase2/plot.py,sha256=txKF6Xnyh2JPJ06Wu803Wn7_VijMMJ1Kbq4WQB-xKE8,22720
16
+ modelbase2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ modelbase2/scan.py,sha256=PvWZA4EgNS0JVMvm87bF72hSmhvo6O2KGg4vRzxve_8,18104
18
+ modelbase2/scope.py,sha256=4twnEh8LrTmlLE-uRvubVkE3SSWejlLvtBzTCPqG3Aw,3710
19
+ modelbase2/simulator.py,sha256=3UIAjGa6AUosd7384I4s9kVyFuY6H0bPcqIm19QpTIQ,19708
20
+ modelbase2/surrogates.py,sha256=XGXZaFwO8CZsATbFohkuK0eQdTR_hsVEUPJyzfIKpSk,9121
21
+ modelbase2/types.py,sha256=N74pWUZDcGlSMfDkjqqwHn5dkozlqgS6Wqg-58YKdvg,9904
22
+ modelbase2/experimental/__init__.py,sha256=En8_KLrfA5RulThEr_Zx2D1n0H0wv1L0Rj6EBwWz7RM,379
23
+ modelbase2/experimental/codegen.py,sha256=J_0iCtojwjmDXAfC8EqiXP0gmWaSH8MPkWvdLsZWsXU,6962
24
+ modelbase2/experimental/diff.py,sha256=e7fjD9kqxkRUNxSevbAznd5cOlEdWJ6pj0y7Kd5KKrw,8973
25
+ modelbase2/experimental/notes.md,sha256=YlM2biTzub6jSlx-aDZaBYsvQcGwb7NHyVAbbl2acGE,238
26
+ modelbase2/experimental/tex.py,sha256=M-Pdq3eQw1Huo-z1gv8EhWVO5ecJyFS8MMy9yoX81VI,13634
27
+ modelbase2/integrators/__init__.py,sha256=kqmV6a0TRyLGR_XqbyAI652AfptYnXAUpqbSFg0CpP8,450
28
+ modelbase2/integrators/int_assimulo.py,sha256=VEQIZFZcEovLPy8i_jR8H8XcxBRQoRVmNzzCYzInPc0,4611
29
+ modelbase2/integrators/int_scipy.py,sha256=-_9MS55eTc9jI7tk-3X49p-c7zrydoXaCCvDTn7Tybw,4334
30
+ modelbase2/sbml/__init__.py,sha256=FBaQsVvrVc7QbCBXuG9tZOdSzHcqmmsaRbFx80rxrac,231
31
+ modelbase2/sbml/_data.py,sha256=XwT1sSxn6KLTXYMbk4ORbEAEgZhQDBfoyrjMBDAoY_s,1135
32
+ modelbase2/sbml/_export.py,sha256=9BLD3Qz86vlfDTZXwOnNOSVWq8mHrJoQjQmKJRZL_Wo,20285
33
+ modelbase2/sbml/_import.py,sha256=uT5JpFvCKjQNBFmGPba61xYShHmjzjczqnaYflilSMI,21523
34
+ modelbase2/sbml/_mathml.py,sha256=bNk9RQ_NQFDhY1R354p-gwqqHaIiyAwZ1xLPHHhiguQ,24436
35
+ modelbase2/sbml/_name_conversion.py,sha256=XK9DEyzhrD0GBBwwjK9RA0yORrDX5c-Uvx0VtKMR5rA,1325
36
+ modelbase2/sbml/_unit_conversion.py,sha256=dW_I6_Ou09ccwnp6LIdrPriIQnQUK5lJcjzM2Fawm6U,1927
37
+ modelbase2/surrogates/__init__.py,sha256=N_iXERECKvmrHiihwnyQEKOSBsmlGEuQhEotn-mWKdk,924
38
+ modelbase2/surrogates/_poly.py,sha256=IRVpuTg5fN8QFQfTdJWpKYoBDhhY8x3BwHWz8fofY3A,3096
39
+ modelbase2/surrogates/_torch.py,sha256=b8kJJjTPLZLgP81ezVo-J2HmaPjyVhTQzDVkzBfkmAQ,5791
40
+ modelbase2-0.3.0.dist-info/METADATA,sha256=EsTsuziNBP-fjSMujjRuHss6XwvxvjDskFkgQhZQeFg,3312
41
+ modelbase2-0.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
42
+ modelbase2-0.3.0.dist-info/licenses/LICENSE,sha256=qvG2VolmSkrcocL34V1ieOx-Rn-fpVcUbb25gHzVgZw,35079
43
+ modelbase2-0.3.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.3.2
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,29 +0,0 @@
1
- from __future__ import annotations
2
-
3
- __all__ = [
4
- "AlgebraicModule",
5
- "AlgebraicModuleContainer",
6
- "Constant",
7
- "ConstantContainer",
8
- "DerivedConstant",
9
- "DerivedStoichiometry",
10
- "NameContainer",
11
- "Reaction",
12
- "ReactionContainer",
13
- "Variable",
14
- "VariableContainer",
15
- ]
16
-
17
- from .algebraic_module_container import AlgebraicModuleContainer
18
- from .constant_container import ConstantContainer
19
- from .data import (
20
- AlgebraicModule,
21
- Constant,
22
- DerivedConstant,
23
- DerivedStoichiometry,
24
- Reaction,
25
- Variable,
26
- )
27
- from .name_container import NameContainer
28
- from .reaction_container import ReactionContainer
29
- from .variable_container import VariableContainer
@@ -1,130 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import logging
4
- from ..types import Array
5
- from .data import AlgebraicModule, ModuleFunction
6
- from dataclasses import dataclass, field
7
- from queue import Empty, SimpleQueue
8
- from typing import Iterable, Iterator, Optional, cast
9
-
10
- logger = logging.getLogger(__name__)
11
-
12
-
13
- @dataclass
14
- class AlgebraicModuleContainer:
15
- modules: dict[str, AlgebraicModule] = field(default_factory=dict)
16
- module_order: list[str] = field(default_factory=list)
17
-
18
- def __iter__(self) -> Iterator[AlgebraicModule]:
19
- return iter(self.modules.values())
20
-
21
- def _sort_algebraic_modules(
22
- self, available_args: set[str], max_iterations: int = 10_000
23
- ) -> None:
24
- module_order = []
25
- modules_to_sort: SimpleQueue[tuple[str, AlgebraicModule]] = SimpleQueue()
26
- for k, v in self.modules.items():
27
- modules_to_sort.put((k, v))
28
-
29
- last_name = None
30
- i = 0
31
- while True:
32
- try:
33
- name, mod = modules_to_sort.get_nowait()
34
- except Empty:
35
- break
36
- if set(mod.args).issubset(available_args):
37
- available_args.update(mod.derived_variables)
38
- module_order.append(name)
39
- else:
40
- if last_name == name:
41
- module_order.append(name)
42
- break
43
- modules_to_sort.put((name, mod))
44
- last_name = name
45
- i += 1
46
- if i > max_iterations:
47
- raise ValueError(
48
- "Exceeded max iterations on algebraic module sorting. Check if there are circular references."
49
- )
50
- self.module_order = module_order
51
-
52
- def get_derived_variables(self) -> list[str]:
53
- return [
54
- variable
55
- for module in self.modules.values()
56
- for variable in module.derived_variables
57
- ]
58
-
59
- def add(
60
- self,
61
- module: AlgebraicModule,
62
- available_args: set[str],
63
- sort_modules: bool,
64
- ) -> None:
65
- if (name := module.name) in self.modules:
66
- raise KeyError(f"Module {name} already exists.")
67
- logger.info(f"Adding algebraic module {name}")
68
- self.modules[name] = module
69
- if sort_modules:
70
- self._sort_algebraic_modules(available_args)
71
-
72
- def update(
73
- self,
74
- name: str,
75
- function: Optional[ModuleFunction],
76
- derived_variables: Optional[list[str]],
77
- args: Optional[list[str]],
78
- available_args: set[str],
79
- ) -> None:
80
- module = self.remove(name, available_args, sort_modules=False)
81
- if function is not None:
82
- module.function = function
83
- if derived_variables is not None:
84
- module.derived_variables = derived_variables
85
- if args is not None:
86
- module.args = args
87
- self.add(module, available_args, sort_modules=True)
88
-
89
- def remove(
90
- self,
91
- name: str,
92
- available_args: set[str],
93
- sort_modules: bool,
94
- ) -> AlgebraicModule:
95
- logger.info(f"Removing algebraic module {name}")
96
- module = self.modules.pop(name)
97
- if sort_modules:
98
- self._sort_algebraic_modules(available_args)
99
- return module
100
-
101
- ##########################################################################
102
- # Simulation functions
103
- ##########################################################################
104
-
105
- def get_values_float(self, args: dict[str, float]) -> dict[str, float]:
106
- derived_variables: dict[str, float] = {}
107
- for name in self.module_order:
108
- module = self.modules[name]
109
- _values = module.function(*(args[arg] for arg in module.args))
110
- values = dict(zip(module.derived_variables, _values))
111
- derived_variables |= values
112
- args |= values
113
- return derived_variables
114
-
115
- def get_values_array(
116
- self,
117
- args: dict[str, Array],
118
- ) -> dict[str, Array]:
119
- derived_variables: dict[str, Array] = {}
120
- for name in self.module_order:
121
- module = self.modules[name]
122
- # values = np.array(module.function(*(args[arg] for arg in module.args)), dtype=float)
123
- # values = values.reshape((len(module.derived_variables), -1))
124
- _values = cast(
125
- Iterable[Array], module.function(*(args[arg] for arg in module.args))
126
- )
127
- values = dict(zip(module.derived_variables, _values))
128
- derived_variables |= values
129
- args |= values
130
- return derived_variables