mxlpy 0.8.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 (48) hide show
  1. mxlpy/__init__.py +165 -0
  2. mxlpy/distributions.py +339 -0
  3. mxlpy/experimental/__init__.py +12 -0
  4. mxlpy/experimental/diff.py +226 -0
  5. mxlpy/fit.py +291 -0
  6. mxlpy/fns.py +191 -0
  7. mxlpy/integrators/__init__.py +19 -0
  8. mxlpy/integrators/int_assimulo.py +146 -0
  9. mxlpy/integrators/int_scipy.py +146 -0
  10. mxlpy/label_map.py +610 -0
  11. mxlpy/linear_label_map.py +303 -0
  12. mxlpy/mc.py +548 -0
  13. mxlpy/mca.py +280 -0
  14. mxlpy/meta/__init__.py +11 -0
  15. mxlpy/meta/codegen_latex.py +516 -0
  16. mxlpy/meta/codegen_modebase.py +110 -0
  17. mxlpy/meta/codegen_py.py +107 -0
  18. mxlpy/meta/source_tools.py +320 -0
  19. mxlpy/model.py +1737 -0
  20. mxlpy/nn/__init__.py +10 -0
  21. mxlpy/nn/_tensorflow.py +0 -0
  22. mxlpy/nn/_torch.py +129 -0
  23. mxlpy/npe.py +277 -0
  24. mxlpy/parallel.py +171 -0
  25. mxlpy/parameterise.py +27 -0
  26. mxlpy/paths.py +36 -0
  27. mxlpy/plot.py +875 -0
  28. mxlpy/py.typed +0 -0
  29. mxlpy/sbml/__init__.py +14 -0
  30. mxlpy/sbml/_data.py +77 -0
  31. mxlpy/sbml/_export.py +644 -0
  32. mxlpy/sbml/_import.py +599 -0
  33. mxlpy/sbml/_mathml.py +691 -0
  34. mxlpy/sbml/_name_conversion.py +52 -0
  35. mxlpy/sbml/_unit_conversion.py +74 -0
  36. mxlpy/scan.py +629 -0
  37. mxlpy/simulator.py +655 -0
  38. mxlpy/surrogates/__init__.py +31 -0
  39. mxlpy/surrogates/_poly.py +97 -0
  40. mxlpy/surrogates/_torch.py +196 -0
  41. mxlpy/symbolic/__init__.py +10 -0
  42. mxlpy/symbolic/strikepy.py +582 -0
  43. mxlpy/symbolic/symbolic_model.py +75 -0
  44. mxlpy/types.py +474 -0
  45. mxlpy-0.8.0.dist-info/METADATA +106 -0
  46. mxlpy-0.8.0.dist-info/RECORD +48 -0
  47. mxlpy-0.8.0.dist-info/WHEEL +4 -0
  48. mxlpy-0.8.0.dist-info/licenses/LICENSE +674 -0
mxlpy/types.py ADDED
@@ -0,0 +1,474 @@
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
+
17
+ from __future__ import annotations
18
+
19
+ from abc import abstractmethod
20
+ from dataclasses import dataclass, field
21
+
22
+ import pandas as pd
23
+
24
+ __all__ = [
25
+ "AbstractSurrogate",
26
+ "Array",
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",
45
+ ]
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
+
53
+ import numpy as np
54
+ import numpy.typing as npt
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 mxlpy.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[Array | None, ArrayLike | None]:
131
+ """Integrate the system."""
132
+ ...
133
+
134
+ def integrate_time_course(
135
+ self, *, time_points: ArrayLike
136
+ ) -> tuple[Array | 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(kw_only=True, slots=True)
151
+ class Derived:
152
+ """Container for a derived value."""
153
+
154
+ name: str
155
+ fn: RateFn
156
+ args: list[str]
157
+
158
+ def calculate(self, dependent: dict[str, float]) -> float:
159
+ """Calculate the derived value.
160
+
161
+ Args:
162
+ dependent: Dictionary of dependent variables.
163
+
164
+ Returns:
165
+ The calculated derived value.
166
+
167
+ """
168
+ return cast(float, self.fn(*(dependent[arg] for arg in self.args)))
169
+
170
+ def calculate_inpl(self, dependent: dict[str, float]) -> None:
171
+ """Calculate the derived value in place.
172
+
173
+ Args:
174
+ dependent: Dictionary of dependent variables.
175
+
176
+ """
177
+ dependent[self.name] = cast(
178
+ float, self.fn(*(dependent[arg] for arg in self.args))
179
+ )
180
+
181
+ def calculate_inpl_time_course(self, dependent: pd.DataFrame) -> None:
182
+ """Calculate the derived value in place.
183
+
184
+ Args:
185
+ dependent: Dictionary of dependent variables.
186
+
187
+ """
188
+ dependent[self.name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
189
+
190
+
191
+ @dataclass(kw_only=True, slots=True)
192
+ class Readout:
193
+ """Container for a readout."""
194
+
195
+ name: str
196
+ fn: RateFn
197
+ args: list[str]
198
+
199
+ def calculate(self, dependent: dict[str, float]) -> float:
200
+ """Calculate the derived value.
201
+
202
+ Args:
203
+ dependent: Dictionary of dependent variables.
204
+
205
+ Returns:
206
+ The calculated derived value.
207
+
208
+ """
209
+ return cast(float, self.fn(*(dependent[arg] for arg in self.args)))
210
+
211
+ def calculate_inpl(self, dependent: dict[str, float]) -> None:
212
+ """Calculate the readout in place.
213
+
214
+ Args:
215
+ dependent: Dictionary of dependent variables.
216
+
217
+ """
218
+ dependent[self.name] = cast(
219
+ float, self.fn(*(dependent[arg] for arg in self.args))
220
+ )
221
+
222
+ def calculate_inpl_time_course(self, dependent: pd.DataFrame) -> None:
223
+ """Calculate the derived value in place.
224
+
225
+ Args:
226
+ dependent: Dictionary of dependent variables.
227
+
228
+ """
229
+ dependent[self.name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
230
+
231
+
232
+ @dataclass(kw_only=True, slots=True)
233
+ class Reaction:
234
+ """Container for a reaction."""
235
+
236
+ name: str
237
+ fn: RateFn
238
+ stoichiometry: Mapping[str, float | Derived]
239
+ args: list[str]
240
+
241
+ def get_modifiers(self, model: Model) -> list[str]:
242
+ """Get the modifiers of the reaction."""
243
+ include = set(model.variables)
244
+ exclude = set(self.stoichiometry)
245
+
246
+ return [k for k in self.args if k in include and k not in exclude]
247
+
248
+ def calculate(self, dependent: dict[str, float]) -> float:
249
+ """Calculate the derived value.
250
+
251
+ Args:
252
+ dependent: Dictionary of dependent variables.
253
+
254
+ Returns:
255
+ The calculated derived value.
256
+
257
+ """
258
+ return cast(float, self.fn(*(dependent[arg] for arg in self.args)))
259
+
260
+ def calculate_inpl(self, dependent: dict[str, float]) -> None:
261
+ """Calculate the reaction in place.
262
+
263
+ Args:
264
+ dependent: Dictionary of dependent variables.
265
+
266
+ """
267
+ dependent[self.name] = cast(
268
+ float, self.fn(*(dependent[arg] for arg in self.args))
269
+ )
270
+
271
+ def calculate_inpl_time_course(self, dependent: pd.DataFrame) -> None:
272
+ """Calculate the derived value in place.
273
+
274
+ Args:
275
+ dependent: Dictionary of dependent variables.
276
+
277
+ """
278
+ try:
279
+ dependent[self.name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
280
+ except ValueError: # e.g. numpy.where
281
+ sub = dependent.loc[:, self.args].to_numpy()
282
+ dependent[self.name] = [self.fn(*row) for row in sub]
283
+
284
+
285
+ @dataclass(kw_only=True, slots=True)
286
+ class ResponseCoefficients:
287
+ """Container for response coefficients."""
288
+
289
+ variables: pd.DataFrame
290
+ fluxes: pd.DataFrame
291
+
292
+ def __iter__(self) -> Iterator[pd.DataFrame]:
293
+ """Iterate over the concentration and flux response coefficients."""
294
+ return iter((self.variables, self.fluxes))
295
+
296
+ @property
297
+ def results(self) -> pd.DataFrame:
298
+ """Return the response coefficients as a DataFrame."""
299
+ return pd.concat((self.variables, self.fluxes), axis=1)
300
+
301
+
302
+ @dataclass(kw_only=True, slots=True)
303
+ class ResponseCoefficientsByPars:
304
+ """Container for response coefficients by parameter."""
305
+
306
+ variables: pd.DataFrame
307
+ fluxes: pd.DataFrame
308
+ parameters: pd.DataFrame
309
+
310
+ def __iter__(self) -> Iterator[pd.DataFrame]:
311
+ """Iterate over the concentration and flux response coefficients."""
312
+ return iter((self.variables, self.fluxes))
313
+
314
+ @property
315
+ def results(self) -> pd.DataFrame:
316
+ """Return the response coefficients as a DataFrame."""
317
+ return pd.concat((self.variables, self.fluxes), axis=1)
318
+
319
+
320
+ @dataclass(kw_only=True, slots=True)
321
+ class SteadyStates:
322
+ """Container for steady states."""
323
+
324
+ variables: pd.DataFrame
325
+ fluxes: pd.DataFrame
326
+ parameters: pd.DataFrame
327
+
328
+ def __iter__(self) -> Iterator[pd.DataFrame]:
329
+ """Iterate over the concentration and flux steady states."""
330
+ return iter((self.variables, self.fluxes))
331
+
332
+ @property
333
+ def results(self) -> pd.DataFrame:
334
+ """Return the steady states as a DataFrame."""
335
+ return pd.concat((self.variables, self.fluxes), axis=1)
336
+
337
+
338
+ @dataclass(kw_only=True, slots=True)
339
+ class McSteadyStates:
340
+ """Container for Monte Carlo steady states."""
341
+
342
+ variables: pd.DataFrame
343
+ fluxes: pd.DataFrame
344
+ parameters: pd.DataFrame
345
+ mc_parameters: pd.DataFrame
346
+
347
+ def __iter__(self) -> Iterator[pd.DataFrame]:
348
+ """Iterate over the concentration and flux steady states."""
349
+ return iter((self.variables, self.fluxes))
350
+
351
+ @property
352
+ def results(self) -> pd.DataFrame:
353
+ """Return the steady states as a DataFrame."""
354
+ return pd.concat((self.variables, self.fluxes), axis=1)
355
+
356
+
357
+ @dataclass(kw_only=True, slots=True)
358
+ class TimeCourseByPars:
359
+ """Container for time courses by parameter."""
360
+
361
+ variables: pd.DataFrame
362
+ fluxes: pd.DataFrame
363
+ parameters: pd.DataFrame
364
+
365
+ def __iter__(self) -> Iterator[pd.DataFrame]:
366
+ """Iterate over the concentration and flux time courses."""
367
+ return iter((self.variables, self.fluxes))
368
+
369
+ @property
370
+ def results(self) -> pd.DataFrame:
371
+ """Return the time courses as a DataFrame."""
372
+ return pd.concat((self.variables, self.fluxes), axis=1)
373
+
374
+ def get_by_name(self, name: str) -> pd.DataFrame:
375
+ """Get time courses by name."""
376
+ return self.results[name].unstack().T
377
+
378
+ def get_agg_per_time(self, agg: str | Callable) -> pd.DataFrame:
379
+ """Get aggregated time courses."""
380
+ mean = cast(pd.DataFrame, self.results.unstack(level=1).agg(agg, axis=0))
381
+ return cast(pd.DataFrame, mean.unstack().T)
382
+
383
+ def get_agg_per_run(self, agg: str | Callable) -> pd.DataFrame:
384
+ """Get aggregated time courses."""
385
+ mean = cast(pd.DataFrame, self.results.unstack(level=0).agg(agg, axis=0))
386
+ return cast(pd.DataFrame, mean.unstack().T)
387
+
388
+
389
+ @dataclass(kw_only=True, slots=True)
390
+ class ProtocolByPars:
391
+ """Container for protocols by parameter."""
392
+
393
+ variables: pd.DataFrame
394
+ fluxes: pd.DataFrame
395
+ parameters: pd.DataFrame
396
+ protocol: pd.DataFrame
397
+
398
+ def __iter__(self) -> Iterator[pd.DataFrame]:
399
+ """Iterate over the concentration and flux protocols."""
400
+ return iter((self.variables, self.fluxes))
401
+
402
+ @property
403
+ def results(self) -> pd.DataFrame:
404
+ """Return the protocols as a DataFrame."""
405
+ return pd.concat((self.variables, self.fluxes), axis=1)
406
+
407
+ def get_by_name(self, name: str) -> pd.DataFrame:
408
+ """Get concentration or flux by name."""
409
+ return self.results[name].unstack().T
410
+
411
+ def get_agg_per_time(self, agg: str | Callable) -> pd.DataFrame:
412
+ """Get aggregated concentration or flux."""
413
+ mean = cast(pd.DataFrame, self.results.unstack(level=1).agg(agg, axis=0))
414
+ return cast(pd.DataFrame, mean.unstack().T)
415
+
416
+ def get_agg_per_run(self, agg: str | Callable) -> pd.DataFrame:
417
+ """Get aggregated concentration or flux."""
418
+ mean = cast(pd.DataFrame, self.results.unstack(level=0).agg(agg, axis=0))
419
+ return cast(pd.DataFrame, mean.unstack().T)
420
+
421
+
422
+ @dataclass(kw_only=True)
423
+ class AbstractSurrogate:
424
+ """Abstract base class for surrogate models.
425
+
426
+ Attributes:
427
+ inputs: List of input variable names.
428
+ stoichiometries: Dictionary mapping reaction names to stoichiometries.
429
+
430
+ Methods:
431
+ predict: Abstract method to predict outputs based on input data.
432
+
433
+ """
434
+
435
+ args: list[str] = field(default_factory=list)
436
+ stoichiometries: dict[str, dict[str, float]] = field(default_factory=dict)
437
+
438
+ @abstractmethod
439
+ def predict_raw(self, y: np.ndarray) -> np.ndarray:
440
+ """Predict outputs based on input data."""
441
+
442
+ def predict(self, y: np.ndarray) -> dict[str, float]:
443
+ """Predict outputs based on input data."""
444
+ return dict(
445
+ zip(
446
+ self.stoichiometries,
447
+ self.predict_raw(y),
448
+ strict=True,
449
+ )
450
+ )
451
+
452
+ def calculate_inpl(self, args: dict[str, float]) -> None:
453
+ """Predict outputs based on input data."""
454
+ args |= self.predict(np.array([args[arg] for arg in self.args]))
455
+
456
+ def calculate_inpl_time_course(self, args: pd.DataFrame) -> None:
457
+ """Predict outputs based on input data."""
458
+ args[list(self.stoichiometries)] = pd.DataFrame(
459
+ [self.predict(y) for y in args.loc[:, self.args].to_numpy()],
460
+ index=args.index,
461
+ dtype=float,
462
+ )
463
+
464
+
465
+ @dataclass(kw_only=True)
466
+ class MockSurrogate(AbstractSurrogate):
467
+ """Mock surrogate model for testing purposes."""
468
+
469
+ def predict(
470
+ self,
471
+ y: np.ndarray,
472
+ ) -> dict[str, float]:
473
+ """Predict outputs based on input data."""
474
+ return dict(zip(self.stoichiometries, y, strict=True))
@@ -0,0 +1,106 @@
1
+ Metadata-Version: 2.4
2
+ Name: mxlpy
3
+ Version: 0.8.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: mike>=2.1.3
29
+ Requires-Dist: more-itertools>=10.5.0
30
+ Requires-Dist: numpy>=2.1.2
31
+ Requires-Dist: pandas>=2.2.3
32
+ Requires-Dist: parameteriser>=0.1.0
33
+ Requires-Dist: pebble>=5.0.7
34
+ Requires-Dist: python-libsbml>=5.20.4
35
+ Requires-Dist: scipy>=1.14.1
36
+ Requires-Dist: seaborn>=0.13.2
37
+ Requires-Dist: symbtools>=0.4.0
38
+ Requires-Dist: sympy>=1.13.1
39
+ Requires-Dist: tabulate>=0.9.0
40
+ Requires-Dist: toml>=0.10.2
41
+ Requires-Dist: tqdm>=4.66.6
42
+ Requires-Dist: typing-extensions>=4.12.2
43
+ Provides-Extra: dev
44
+ Requires-Dist: coverage>=7.6.4; extra == 'dev'
45
+ Requires-Dist: jupyter>=1.1.1; extra == 'dev'
46
+ Requires-Dist: mkdocs-jupyter>=0.25.1; extra == 'dev'
47
+ Requires-Dist: mkdocs-material>=9.5.42; extra == 'dev'
48
+ Requires-Dist: mkdocs>=1.6.1; extra == 'dev'
49
+ Requires-Dist: mypy>=1.13.0; extra == 'dev'
50
+ Requires-Dist: pre-commit>=4.0.1; extra == 'dev'
51
+ Requires-Dist: pyright>=1.1.387; extra == 'dev'
52
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
53
+ Requires-Dist: pytest>=8.3.3; extra == 'dev'
54
+ Requires-Dist: requests>=2.32.3; extra == 'dev'
55
+ Requires-Dist: ruff>=0.7.1; extra == 'dev'
56
+ Requires-Dist: ssort>=0.13.0; extra == 'dev'
57
+ Requires-Dist: toml-sort<0.24,>=0.23.1; extra == 'dev'
58
+ Provides-Extra: torch
59
+ Requires-Dist: torch>=2.5.1; extra == 'torch'
60
+ Description-Content-Type: text/markdown
61
+
62
+ # mxlpy
63
+
64
+ [![pypi](https://img.shields.io/pypi/v/mxlpy.svg)](https://pypi.python.org/pypi/mxlpy)
65
+ [![docs][docs-badge]][docs]
66
+ ![License](https://img.shields.io/badge/license-GPL--3.0-blue?style=flat-square)
67
+ ![Coverage](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fgist.github.com%2Fmarvinvanaalst%2F98ab3ce1db511de42f9871e91d85e4cd%2Fraw%2Fcoverage.json&query=%24.message&label=Coverage&color=%24.color&suffix=%20%25)
68
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
69
+ [![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
70
+ [![Downloads](https://pepy.tech/badge/mxlpy)](https://pepy.tech/project/mxlpy)
71
+
72
+ [docs-badge]: https://img.shields.io/badge/docs-main-green.svg?style=flat-square
73
+ [docs]: https://computational-biology-aachen.github.io/mxlpy/
74
+
75
+ ## Installation
76
+
77
+ You can install mxlpy using pip: `pip install mxlpy`
78
+
79
+ 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.
80
+
81
+ ```bash
82
+ pixi init
83
+ pixi add python assimulo
84
+ pixi add --pypi mxlpy[torch]
85
+ ```
86
+
87
+
88
+ ## Development setup
89
+
90
+ You have two choices here, using `uv` (pypi-only) or using `pixi` (conda-forge, including assimulo)
91
+
92
+ ### uv
93
+
94
+ - Install `uv` as described in [the docs](https://docs.astral.sh/uv/getting-started/installation/).
95
+ - Run `uv sync --extra dev --extra torch` to install dependencies locally
96
+
97
+ ### pixi
98
+
99
+ - Install `pixi` as described in [the docs](https://pixi.sh/latest/#installation)
100
+ - Run `pixi install --frozen`
101
+
102
+
103
+ ## Notes
104
+
105
+ - `uv add $package`
106
+ - `uv add --optional dev $package`
@@ -0,0 +1,48 @@
1
+ mxlpy/__init__.py,sha256=HwV_l1PqCqWsn1TFwUMslbfuPjX6cUGzytyWPaUz4FM,4168
2
+ mxlpy/distributions.py,sha256=ce6RTqn19YzMMec-u09fSIUA8A92M6rehCuHuXWcX7A,8734
3
+ mxlpy/fit.py,sha256=M8F5s9RUoUPr2s-pCLFZD_ebP2uGvajNCn7XYh1w7Tc,8078
4
+ mxlpy/fns.py,sha256=ct_RFj9koW8vXHyr27GnbZUHUS_zfs4rDysybuFiOaU,4599
5
+ mxlpy/label_map.py,sha256=urv-QTb0MUEKjwWvKtJSB8H2kvhLn1EKfRIH7awQQ8Y,17769
6
+ mxlpy/linear_label_map.py,sha256=2lgERcUVDLXruRI08HBYJo_wK654y46voLUeBTzBy3k,10312
7
+ mxlpy/mc.py,sha256=L4IFYmnq8GvSnuhbF-UBVWQf77e1Pu-vr4PPim5Fk5w,16303
8
+ mxlpy/mca.py,sha256=JNJf0vCqKzFTQ6-og-nnamX_-phml8iQC5OKfbSjqC0,8869
9
+ mxlpy/model.py,sha256=-BmS4bGCq_fMUnRLZG5uwl86ip_SiaWxsbgLPeV0nHQ,57656
10
+ mxlpy/npe.py,sha256=oiRLA43-qf-AcS2KpQfJIOt7-Ev9Aj5sF6TMq9bJn84,8747
11
+ mxlpy/parallel.py,sha256=kX4Td5YoovDwZp6kX_3cfO6QtHSS9ieJ0bMZiKs3Xv8,5002
12
+ mxlpy/parameterise.py,sha256=2jMhhO-bHTFP_0kXercJekeATAZYBg5FrK1MQ_mWGpk,654
13
+ mxlpy/paths.py,sha256=TK2wO4N9lG-UV1JGfeB64q48JVDbwqIUj63rl55MKuQ,1022
14
+ mxlpy/plot.py,sha256=1sI18HAQXeBNo_H6ctS9pwLdmp3MSkGgaGQK7IrTUBc,23498
15
+ mxlpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ mxlpy/scan.py,sha256=vDmFiWoGtT4C__Z617ig9HMIOkuQptT12vKYnlEp7Ao,17738
17
+ mxlpy/simulator.py,sha256=T9t2jZ6U5NyK1ICF1UkST8M8v4EPV_H98kzZ4TvQK-w,20115
18
+ mxlpy/types.py,sha256=ksdn76Sdw0XhQEpQepcETvuGqcJolfrmbIRBT0R_2Bg,13612
19
+ mxlpy/experimental/__init__.py,sha256=kZTE-92OErpHzNRqmgSQYH4CGXrogGJ5EL35XGZQ81M,206
20
+ mxlpy/experimental/diff.py,sha256=4bztagJzFMsQJM7dlun_kv-WrWssM8CIw7gcL63hFf8,8952
21
+ mxlpy/integrators/__init__.py,sha256=kqmV6a0TRyLGR_XqbyAI652AfptYnXAUpqbSFg0CpP8,450
22
+ mxlpy/integrators/int_assimulo.py,sha256=Y9jvpJWXkmueUyjDnu_6SqDntyMdG_DU370EtuRyMqA,4605
23
+ mxlpy/integrators/int_scipy.py,sha256=Z9LSwqBKgYfwmrNiMxJ3-vRad5n_yQo1Ime4WDAAZEI,4343
24
+ mxlpy/meta/__init__.py,sha256=Jyy4063fZy6iT4LSwjPyEAVr4N_3xxcLc8wDBoDPyKc,278
25
+ mxlpy/meta/codegen_latex.py,sha256=1z0waYPmohY9GTJ_5DBuwXOXGTCHCH8E14tg6MYsf2A,13460
26
+ mxlpy/meta/codegen_modebase.py,sha256=qQ8p6_KqMYCw7SRmf2HHRGvl25sYPKVI_zWKhzFhFLw,3138
27
+ mxlpy/meta/codegen_py.py,sha256=xSdeuEGPGc-QKRMgJO4VSPGMlxCPEV5prkKjNQ2D2hg,3483
28
+ mxlpy/meta/source_tools.py,sha256=EN3OoGQaXeIsDTJvA7S15-xDBra3DCIyFZEJ6h0Fy0k,11125
29
+ mxlpy/nn/__init__.py,sha256=yUc4o-iqfVVzkq9tZCstWwizrCqNlMft0YUwWGFFO-E,219
30
+ mxlpy/nn/_tensorflow.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ mxlpy/nn/_torch.py,sha256=_4Rw87zpIlCnrOsXC7iFp1c64_FcpfVmgBXBU0p8mlg,4063
32
+ mxlpy/sbml/__init__.py,sha256=AS7IwrBzBgN8coUZkyBEtiYa9ICWyY1wzp1ujVm5ItA,226
33
+ mxlpy/sbml/_data.py,sha256=XwT1sSxn6KLTXYMbk4ORbEAEgZhQDBfoyrjMBDAoY_s,1135
34
+ mxlpy/sbml/_export.py,sha256=Q6B9rxy-yt73DORzAYu4BpfkZXxCS3MDSDUXwpoXV6Q,19970
35
+ mxlpy/sbml/_import.py,sha256=5DJklsAe2sMV1CFxAbkSFRT3amPzOZmpo53y9NYv6TY,22015
36
+ mxlpy/sbml/_mathml.py,sha256=bNk9RQ_NQFDhY1R354p-gwqqHaIiyAwZ1xLPHHhiguQ,24436
37
+ mxlpy/sbml/_name_conversion.py,sha256=XK9DEyzhrD0GBBwwjK9RA0yORrDX5c-Uvx0VtKMR5rA,1325
38
+ mxlpy/sbml/_unit_conversion.py,sha256=dW_I6_Ou09ccwnp6LIdrPriIQnQUK5lJcjzM2Fawm6U,1927
39
+ mxlpy/surrogates/__init__.py,sha256=N_iXERECKvmrHiihwnyQEKOSBsmlGEuQhEotn-mWKdk,924
40
+ mxlpy/surrogates/_poly.py,sha256=E54CFscQBCcYMrty1X2ynl9GlS9uoEeAUgBPnhm3iIA,3113
41
+ mxlpy/surrogates/_torch.py,sha256=E_1eDUlPSVFwROkdMDCqYwwHE-61pjNMJWotnhjzge0,5891
42
+ mxlpy/symbolic/__init__.py,sha256=3hQjCMw8-6iOxeUdfnCg8449fF_BRF2u6lCM1GPpkRY,222
43
+ mxlpy/symbolic/strikepy.py,sha256=r6nRtckV1nxKq3i1bYYWZOkzwZ5XeKQuZM5ck44vUo0,20010
44
+ mxlpy/symbolic/symbolic_model.py,sha256=YL9noEeP3_0DoKXwMPELtfmPuP6mgNcLIJgDRCkyB7A,2434
45
+ mxlpy-0.8.0.dist-info/METADATA,sha256=EJiGUDewxhWeWCVzxuVhSSjfDYE3ao4XTYQaUKIwMyU,4245
46
+ mxlpy-0.8.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
47
+ mxlpy-0.8.0.dist-info/licenses/LICENSE,sha256=bEzjyjy1stQhfRDVaVHa3xV1x-V8emwdlbMvYO8Zo84,35073
48
+ mxlpy-0.8.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any