mxlpy 0.22.0__py3-none-any.whl → 0.24.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 +13 -6
- mxlpy/carousel.py +52 -5
- mxlpy/compare.py +15 -2
- mxlpy/experimental/diff.py +14 -0
- mxlpy/fit.py +20 -1
- mxlpy/integrators/__init__.py +4 -0
- mxlpy/integrators/int_assimulo.py +3 -3
- mxlpy/integrators/int_diffrax.py +119 -0
- mxlpy/integrators/int_scipy.py +12 -6
- mxlpy/label_map.py +1 -2
- mxlpy/mc.py +85 -24
- mxlpy/mca.py +8 -4
- mxlpy/meta/__init__.py +6 -1
- mxlpy/meta/codegen_latex.py +9 -0
- mxlpy/meta/codegen_model.py +55 -12
- mxlpy/meta/codegen_mxlpy.py +215 -58
- mxlpy/meta/source_tools.py +129 -80
- mxlpy/meta/sympy_tools.py +12 -6
- mxlpy/model.py +314 -96
- mxlpy/plot.py +60 -29
- mxlpy/sbml/_data.py +34 -0
- mxlpy/sbml/_export.py +17 -8
- mxlpy/sbml/_import.py +68 -547
- mxlpy/scan.py +163 -249
- mxlpy/simulator.py +9 -359
- mxlpy/types.py +723 -80
- mxlpy/units.py +5 -0
- {mxlpy-0.22.0.dist-info → mxlpy-0.24.0.dist-info}/METADATA +7 -1
- mxlpy-0.24.0.dist-info/RECORD +57 -0
- mxlpy/sbml/_mathml.py +0 -692
- mxlpy/sbml/_unit_conversion.py +0 -74
- mxlpy-0.22.0.dist-info/RECORD +0 -58
- {mxlpy-0.22.0.dist-info → mxlpy-0.24.0.dist-info}/WHEEL +0 -0
- {mxlpy-0.22.0.dist-info → mxlpy-0.24.0.dist-info}/licenses/LICENSE +0 -0
mxlpy/simulator.py
CHANGED
@@ -11,383 +11,29 @@ Classes:
|
|
11
11
|
from __future__ import annotations
|
12
12
|
|
13
13
|
import logging
|
14
|
-
from dataclasses import dataclass
|
15
|
-
from typing import TYPE_CHECKING,
|
14
|
+
from dataclasses import dataclass
|
15
|
+
from typing import TYPE_CHECKING, Self, cast
|
16
16
|
|
17
17
|
import numpy as np
|
18
18
|
import pandas as pd
|
19
19
|
from sympy import lambdify
|
20
|
+
from wadler_lindig import pformat
|
20
21
|
|
21
22
|
from mxlpy.integrators import DefaultIntegrator
|
22
23
|
from mxlpy.symbolic import to_symbolic_model
|
24
|
+
from mxlpy.types import Result
|
23
25
|
|
24
26
|
if TYPE_CHECKING:
|
25
|
-
from collections.abc import Iterator
|
26
|
-
|
27
27
|
from mxlpy.model import Model
|
28
28
|
from mxlpy.types import Array, ArrayLike, IntegratorProtocol, IntegratorType
|
29
29
|
|
30
30
|
_LOGGER = logging.getLogger(__name__)
|
31
31
|
|
32
32
|
__all__ = [
|
33
|
-
"Result",
|
34
33
|
"Simulator",
|
35
34
|
]
|
36
35
|
|
37
36
|
|
38
|
-
def _normalise_split_results(
|
39
|
-
results: list[pd.DataFrame],
|
40
|
-
normalise: float | ArrayLike,
|
41
|
-
) -> list[pd.DataFrame]:
|
42
|
-
"""Normalize split results by a given factor or array.
|
43
|
-
|
44
|
-
Args:
|
45
|
-
results: List of DataFrames containing the results to normalize.
|
46
|
-
normalise: Normalization factor or array.
|
47
|
-
|
48
|
-
Returns:
|
49
|
-
list[pd.DataFrame]: List of normalized DataFrames.
|
50
|
-
|
51
|
-
"""
|
52
|
-
if isinstance(normalise, int | float):
|
53
|
-
return [i / normalise for i in results]
|
54
|
-
if len(normalise) == len(results):
|
55
|
-
return [(i.T / j).T for i, j in zip(results, normalise, strict=True)]
|
56
|
-
|
57
|
-
results = []
|
58
|
-
start = 0
|
59
|
-
end = 0
|
60
|
-
for i in results:
|
61
|
-
end += len(i)
|
62
|
-
results.append(i / np.reshape(normalise[start:end], (len(i), 1))) # type: ignore
|
63
|
-
start += end
|
64
|
-
return results
|
65
|
-
|
66
|
-
|
67
|
-
@dataclass(kw_only=True, slots=True)
|
68
|
-
class Result:
|
69
|
-
"""Simulation results."""
|
70
|
-
|
71
|
-
model: Model
|
72
|
-
raw_variables: list[pd.DataFrame]
|
73
|
-
raw_parameters: list[dict[str, float]]
|
74
|
-
raw_args: list[pd.DataFrame] = field(default_factory=list)
|
75
|
-
|
76
|
-
@property
|
77
|
-
def variables(self) -> pd.DataFrame:
|
78
|
-
"""Simulation variables."""
|
79
|
-
return self.get_variables(
|
80
|
-
include_derived_variables=True,
|
81
|
-
include_readouts=True,
|
82
|
-
concatenated=True,
|
83
|
-
normalise=None,
|
84
|
-
)
|
85
|
-
|
86
|
-
@property
|
87
|
-
def fluxes(self) -> pd.DataFrame:
|
88
|
-
"""Simulation fluxes."""
|
89
|
-
return self.get_fluxes()
|
90
|
-
|
91
|
-
def __iter__(self) -> Iterator[pd.DataFrame]:
|
92
|
-
"""Iterate over the concentration and flux response coefficients."""
|
93
|
-
return iter((self.variables, self.fluxes))
|
94
|
-
|
95
|
-
def _compute_args(self) -> list[pd.DataFrame]:
|
96
|
-
# Already computed
|
97
|
-
if len(self.raw_args) > 0:
|
98
|
-
return self.raw_args
|
99
|
-
|
100
|
-
# Compute new otherwise
|
101
|
-
for res, p in zip(self.raw_variables, self.raw_parameters, strict=True):
|
102
|
-
self.model.update_parameters(p)
|
103
|
-
self.raw_args.append(
|
104
|
-
self.model.get_args_time_course(
|
105
|
-
variables=res,
|
106
|
-
include_variables=True,
|
107
|
-
include_parameters=True,
|
108
|
-
include_derived_parameters=True,
|
109
|
-
include_derived_variables=True,
|
110
|
-
include_reactions=True,
|
111
|
-
include_surrogate_outputs=True,
|
112
|
-
include_readouts=True,
|
113
|
-
)
|
114
|
-
)
|
115
|
-
return self.raw_args
|
116
|
-
|
117
|
-
def _select_data(
|
118
|
-
self,
|
119
|
-
dependent: list[pd.DataFrame],
|
120
|
-
*,
|
121
|
-
include_variables: bool = False,
|
122
|
-
include_parameters: bool = False,
|
123
|
-
include_derived_parameters: bool = False,
|
124
|
-
include_derived_variables: bool = False,
|
125
|
-
include_reactions: bool = False,
|
126
|
-
include_surrogate_outputs: bool = False,
|
127
|
-
include_readouts: bool = False,
|
128
|
-
) -> list[pd.DataFrame]:
|
129
|
-
names = self.model.get_arg_names(
|
130
|
-
include_time=False,
|
131
|
-
include_variables=include_variables,
|
132
|
-
include_parameters=include_parameters,
|
133
|
-
include_derived_parameters=include_derived_parameters,
|
134
|
-
include_derived_variables=include_derived_variables,
|
135
|
-
include_reactions=include_reactions,
|
136
|
-
include_surrogate_outputs=include_surrogate_outputs,
|
137
|
-
include_readouts=include_readouts,
|
138
|
-
)
|
139
|
-
return [i.loc[:, names] for i in dependent]
|
140
|
-
|
141
|
-
def _adjust_data(
|
142
|
-
self,
|
143
|
-
data: list[pd.DataFrame],
|
144
|
-
normalise: float | ArrayLike | None = None,
|
145
|
-
*,
|
146
|
-
concatenated: bool = True,
|
147
|
-
) -> pd.DataFrame | list[pd.DataFrame]:
|
148
|
-
if normalise is not None:
|
149
|
-
data = _normalise_split_results(data, normalise=normalise)
|
150
|
-
if concatenated:
|
151
|
-
return pd.concat(data, axis=0)
|
152
|
-
return data
|
153
|
-
|
154
|
-
@overload
|
155
|
-
def get_args( # type: ignore
|
156
|
-
self,
|
157
|
-
*,
|
158
|
-
include_variables: bool = True,
|
159
|
-
include_parameters: bool = False,
|
160
|
-
include_derived_parameters: bool = False,
|
161
|
-
include_derived_variables: bool = True,
|
162
|
-
include_reactions: bool = True,
|
163
|
-
include_surrogate_outputs: bool = False,
|
164
|
-
include_readouts: bool = False,
|
165
|
-
concatenated: Literal[False],
|
166
|
-
normalise: float | ArrayLike | None = None,
|
167
|
-
) -> list[pd.DataFrame]: ...
|
168
|
-
|
169
|
-
@overload
|
170
|
-
def get_args(
|
171
|
-
self,
|
172
|
-
*,
|
173
|
-
include_variables: bool = True,
|
174
|
-
include_parameters: bool = False,
|
175
|
-
include_derived_parameters: bool = False,
|
176
|
-
include_derived_variables: bool = True,
|
177
|
-
include_reactions: bool = True,
|
178
|
-
include_surrogate_outputs: bool = False,
|
179
|
-
include_readouts: bool = False,
|
180
|
-
concatenated: Literal[True],
|
181
|
-
normalise: float | ArrayLike | None = None,
|
182
|
-
) -> pd.DataFrame: ...
|
183
|
-
|
184
|
-
@overload
|
185
|
-
def get_args(
|
186
|
-
self,
|
187
|
-
*,
|
188
|
-
include_variables: bool = True,
|
189
|
-
include_parameters: bool = False,
|
190
|
-
include_derived_parameters: bool = False,
|
191
|
-
include_derived_variables: bool = True,
|
192
|
-
include_reactions: bool = True,
|
193
|
-
include_surrogate_outputs: bool = False,
|
194
|
-
include_readouts: bool = False,
|
195
|
-
concatenated: bool = True,
|
196
|
-
normalise: float | ArrayLike | None = None,
|
197
|
-
) -> pd.DataFrame: ...
|
198
|
-
|
199
|
-
def get_args(
|
200
|
-
self,
|
201
|
-
*,
|
202
|
-
include_variables: bool = True,
|
203
|
-
include_parameters: bool = False,
|
204
|
-
include_derived_parameters: bool = False,
|
205
|
-
include_derived_variables: bool = True,
|
206
|
-
include_reactions: bool = True,
|
207
|
-
include_surrogate_outputs: bool = False,
|
208
|
-
include_readouts: bool = False,
|
209
|
-
concatenated: bool = True,
|
210
|
-
normalise: float | ArrayLike | None = None,
|
211
|
-
) -> pd.DataFrame | list[pd.DataFrame]:
|
212
|
-
"""Get the variables over time.
|
213
|
-
|
214
|
-
Examples:
|
215
|
-
>>> Result().get_variables()
|
216
|
-
Time ATP NADPH
|
217
|
-
0.000000 1.000000 1.000000
|
218
|
-
0.000100 0.999900 0.999900
|
219
|
-
0.000200 0.999800 0.999800
|
220
|
-
|
221
|
-
"""
|
222
|
-
variables = self._select_data(
|
223
|
-
self._compute_args(),
|
224
|
-
include_variables=include_variables,
|
225
|
-
include_parameters=include_parameters,
|
226
|
-
include_derived_parameters=include_derived_parameters,
|
227
|
-
include_derived_variables=include_derived_variables,
|
228
|
-
include_reactions=include_reactions,
|
229
|
-
include_surrogate_outputs=include_surrogate_outputs,
|
230
|
-
include_readouts=include_readouts,
|
231
|
-
)
|
232
|
-
return self._adjust_data(
|
233
|
-
variables, normalise=normalise, concatenated=concatenated
|
234
|
-
)
|
235
|
-
|
236
|
-
@overload
|
237
|
-
def get_variables( # type: ignore
|
238
|
-
self,
|
239
|
-
*,
|
240
|
-
include_derived_variables: bool = True,
|
241
|
-
include_readouts: bool = True,
|
242
|
-
concatenated: Literal[False],
|
243
|
-
normalise: float | ArrayLike | None = None,
|
244
|
-
) -> list[pd.DataFrame]: ...
|
245
|
-
|
246
|
-
@overload
|
247
|
-
def get_variables(
|
248
|
-
self,
|
249
|
-
*,
|
250
|
-
include_derived_variables: bool = True,
|
251
|
-
include_readouts: bool = True,
|
252
|
-
concatenated: Literal[True],
|
253
|
-
normalise: float | ArrayLike | None = None,
|
254
|
-
) -> pd.DataFrame: ...
|
255
|
-
|
256
|
-
@overload
|
257
|
-
def get_variables(
|
258
|
-
self,
|
259
|
-
*,
|
260
|
-
include_derived_variables: bool = True,
|
261
|
-
include_readouts: bool = True,
|
262
|
-
concatenated: bool = True,
|
263
|
-
normalise: float | ArrayLike | None = None,
|
264
|
-
) -> pd.DataFrame: ...
|
265
|
-
|
266
|
-
def get_variables(
|
267
|
-
self,
|
268
|
-
*,
|
269
|
-
include_derived_variables: bool = True,
|
270
|
-
include_readouts: bool = True,
|
271
|
-
concatenated: bool = True,
|
272
|
-
normalise: float | ArrayLike | None = None,
|
273
|
-
) -> pd.DataFrame | list[pd.DataFrame]:
|
274
|
-
"""Get the variables over time.
|
275
|
-
|
276
|
-
Examples:
|
277
|
-
>>> Result().get_variables()
|
278
|
-
Time ATP NADPH
|
279
|
-
0.000000 1.000000 1.000000
|
280
|
-
0.000100 0.999900 0.999900
|
281
|
-
0.000200 0.999800 0.999800
|
282
|
-
|
283
|
-
"""
|
284
|
-
if not include_derived_variables and not include_readouts:
|
285
|
-
return self._adjust_data(
|
286
|
-
self.raw_variables,
|
287
|
-
normalise=normalise,
|
288
|
-
concatenated=concatenated,
|
289
|
-
)
|
290
|
-
|
291
|
-
variables = self._select_data(
|
292
|
-
self._compute_args(),
|
293
|
-
include_variables=True,
|
294
|
-
include_derived_variables=include_derived_variables,
|
295
|
-
include_readouts=include_readouts,
|
296
|
-
)
|
297
|
-
return self._adjust_data(
|
298
|
-
variables, normalise=normalise, concatenated=concatenated
|
299
|
-
)
|
300
|
-
|
301
|
-
@overload
|
302
|
-
def get_fluxes( # type: ignore
|
303
|
-
self,
|
304
|
-
*,
|
305
|
-
include_surrogates: bool = True,
|
306
|
-
normalise: float | ArrayLike | None = None,
|
307
|
-
concatenated: Literal[False],
|
308
|
-
) -> list[pd.DataFrame]: ...
|
309
|
-
|
310
|
-
@overload
|
311
|
-
def get_fluxes(
|
312
|
-
self,
|
313
|
-
*,
|
314
|
-
include_surrogates: bool = True,
|
315
|
-
normalise: float | ArrayLike | None = None,
|
316
|
-
concatenated: Literal[True],
|
317
|
-
) -> pd.DataFrame: ...
|
318
|
-
|
319
|
-
@overload
|
320
|
-
def get_fluxes(
|
321
|
-
self,
|
322
|
-
*,
|
323
|
-
include_surrogates: bool = True,
|
324
|
-
normalise: float | ArrayLike | None = None,
|
325
|
-
concatenated: bool = True,
|
326
|
-
) -> pd.DataFrame: ...
|
327
|
-
|
328
|
-
def get_fluxes(
|
329
|
-
self,
|
330
|
-
*,
|
331
|
-
include_surrogates: bool = True,
|
332
|
-
normalise: float | ArrayLike | None = None,
|
333
|
-
concatenated: bool = True,
|
334
|
-
) -> pd.DataFrame | list[pd.DataFrame]:
|
335
|
-
"""Get the flux results.
|
336
|
-
|
337
|
-
Examples:
|
338
|
-
>>> Result.get_fluxes()
|
339
|
-
Time v1 v2
|
340
|
-
0.000000 1.000000 10.00000
|
341
|
-
0.000100 0.999900 9.999000
|
342
|
-
0.000200 0.999800 9.998000
|
343
|
-
|
344
|
-
Returns:
|
345
|
-
pd.DataFrame: DataFrame of fluxes.
|
346
|
-
|
347
|
-
"""
|
348
|
-
fluxes = self._select_data(
|
349
|
-
self._compute_args(),
|
350
|
-
include_reactions=True,
|
351
|
-
include_surrogate_outputs=include_surrogates,
|
352
|
-
)
|
353
|
-
return self._adjust_data(
|
354
|
-
fluxes,
|
355
|
-
normalise=normalise,
|
356
|
-
concatenated=concatenated,
|
357
|
-
)
|
358
|
-
|
359
|
-
def get_combined(self) -> pd.DataFrame:
|
360
|
-
"""Get the variables and fluxes as a single pandas.DataFrame.
|
361
|
-
|
362
|
-
Examples:
|
363
|
-
>>> Result.get_combined()
|
364
|
-
Time ATP NADPH v1 v2
|
365
|
-
0.000000 1.000000 1.000000 1.000000 10.00000
|
366
|
-
0.000100 0.999900 0.999900 0.999900 9.999000
|
367
|
-
0.000200 0.999800 0.999800 0.999800 9.998000
|
368
|
-
|
369
|
-
Returns:
|
370
|
-
pd.DataFrame: DataFrame of fluxes.
|
371
|
-
|
372
|
-
"""
|
373
|
-
return pd.concat((self.variables, self.fluxes), axis=1)
|
374
|
-
|
375
|
-
def get_new_y0(self) -> dict[str, float]:
|
376
|
-
"""Get the new initial conditions after the simulation.
|
377
|
-
|
378
|
-
Examples:
|
379
|
-
>>> Simulator(model).simulate_to_steady_state().get_new_y0()
|
380
|
-
{"ATP": 1.0, "NADPH": 1.0}
|
381
|
-
|
382
|
-
"""
|
383
|
-
return dict(
|
384
|
-
self.get_variables(
|
385
|
-
include_derived_variables=False,
|
386
|
-
include_readouts=False,
|
387
|
-
).iloc[-1]
|
388
|
-
)
|
389
|
-
|
390
|
-
|
391
37
|
@dataclass(
|
392
38
|
init=False,
|
393
39
|
slots=True,
|
@@ -418,6 +64,10 @@ class Simulator:
|
|
418
64
|
_integrator_type: IntegratorType
|
419
65
|
_time_shift: float | None
|
420
66
|
|
67
|
+
def __repr__(self) -> str:
|
68
|
+
"""Return default representation."""
|
69
|
+
return pformat(self)
|
70
|
+
|
421
71
|
def __init__(
|
422
72
|
self,
|
423
73
|
model: Model,
|
@@ -478,7 +128,7 @@ class Simulator:
|
|
478
128
|
y0 = self.y0
|
479
129
|
self.integrator = self._integrator_type(
|
480
130
|
self.model,
|
481
|
-
|
131
|
+
tuple(y0[k] for k in self.model.get_variable_names()),
|
482
132
|
jac_fn,
|
483
133
|
)
|
484
134
|
|