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.
- mxlpy/__init__.py +165 -0
- mxlpy/distributions.py +339 -0
- mxlpy/experimental/__init__.py +12 -0
- mxlpy/experimental/diff.py +226 -0
- mxlpy/fit.py +291 -0
- mxlpy/fns.py +191 -0
- mxlpy/integrators/__init__.py +19 -0
- mxlpy/integrators/int_assimulo.py +146 -0
- mxlpy/integrators/int_scipy.py +146 -0
- mxlpy/label_map.py +610 -0
- mxlpy/linear_label_map.py +303 -0
- mxlpy/mc.py +548 -0
- mxlpy/mca.py +280 -0
- mxlpy/meta/__init__.py +11 -0
- mxlpy/meta/codegen_latex.py +516 -0
- mxlpy/meta/codegen_modebase.py +110 -0
- mxlpy/meta/codegen_py.py +107 -0
- mxlpy/meta/source_tools.py +320 -0
- mxlpy/model.py +1737 -0
- mxlpy/nn/__init__.py +10 -0
- mxlpy/nn/_tensorflow.py +0 -0
- mxlpy/nn/_torch.py +129 -0
- mxlpy/npe.py +277 -0
- mxlpy/parallel.py +171 -0
- mxlpy/parameterise.py +27 -0
- mxlpy/paths.py +36 -0
- mxlpy/plot.py +875 -0
- mxlpy/py.typed +0 -0
- mxlpy/sbml/__init__.py +14 -0
- mxlpy/sbml/_data.py +77 -0
- mxlpy/sbml/_export.py +644 -0
- mxlpy/sbml/_import.py +599 -0
- mxlpy/sbml/_mathml.py +691 -0
- mxlpy/sbml/_name_conversion.py +52 -0
- mxlpy/sbml/_unit_conversion.py +74 -0
- mxlpy/scan.py +629 -0
- mxlpy/simulator.py +655 -0
- mxlpy/surrogates/__init__.py +31 -0
- mxlpy/surrogates/_poly.py +97 -0
- mxlpy/surrogates/_torch.py +196 -0
- mxlpy/symbolic/__init__.py +10 -0
- mxlpy/symbolic/strikepy.py +582 -0
- mxlpy/symbolic/symbolic_model.py +75 -0
- mxlpy/types.py +474 -0
- mxlpy-0.8.0.dist-info/METADATA +106 -0
- mxlpy-0.8.0.dist-info/RECORD +48 -0
- mxlpy-0.8.0.dist-info/WHEEL +4 -0
- 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
|
+
[](https://pypi.python.org/pypi/mxlpy)
|
65
|
+
[![docs][docs-badge]][docs]
|
66
|
+

|
67
|
+

|
68
|
+
[](https://github.com/astral-sh/ruff)
|
69
|
+
[](https://github.com/PyCQA/bandit)
|
70
|
+
[](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,,
|