mxlpy 0.15.0__py3-none-any.whl → 0.17.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 +4 -1
- mxlpy/fns.py +513 -21
- mxlpy/integrators/int_assimulo.py +2 -1
- mxlpy/mc.py +84 -70
- mxlpy/mca.py +97 -98
- mxlpy/meta/codegen_latex.py +279 -14
- mxlpy/meta/source_tools.py +122 -4
- mxlpy/model.py +50 -24
- mxlpy/npe/__init__.py +38 -0
- mxlpy/npe/_torch.py +436 -0
- mxlpy/report.py +33 -6
- mxlpy/sbml/_import.py +5 -2
- mxlpy/scan.py +40 -38
- mxlpy/surrogates/__init__.py +7 -6
- mxlpy/surrogates/_poly.py +12 -9
- mxlpy/surrogates/_torch.py +137 -43
- mxlpy/symbolic/strikepy.py +1 -3
- mxlpy/types.py +18 -5
- {mxlpy-0.15.0.dist-info → mxlpy-0.17.0.dist-info}/METADATA +5 -4
- {mxlpy-0.15.0.dist-info → mxlpy-0.17.0.dist-info}/RECORD +22 -21
- mxlpy/npe.py +0 -277
- {mxlpy-0.15.0.dist-info → mxlpy-0.17.0.dist-info}/WHEEL +0 -0
- {mxlpy-0.15.0.dist-info → mxlpy-0.17.0.dist-info}/licenses/LICENSE +0 -0
mxlpy/mca.py
CHANGED
@@ -38,6 +38,73 @@ if TYPE_CHECKING:
|
|
38
38
|
from mxlpy.types import IntegratorType
|
39
39
|
|
40
40
|
|
41
|
+
def _response_coefficient_worker(
|
42
|
+
parameter: str,
|
43
|
+
*,
|
44
|
+
model: Model,
|
45
|
+
y0: dict[str, float] | None,
|
46
|
+
normalized: bool,
|
47
|
+
rel_norm: bool,
|
48
|
+
displacement: float = 1e-4,
|
49
|
+
integrator: IntegratorType,
|
50
|
+
) -> tuple[pd.Series, pd.Series]:
|
51
|
+
"""Calculate response coefficients for a single parameter.
|
52
|
+
|
53
|
+
Internal helper function that computes concentration and flux response
|
54
|
+
coefficients using finite differences. The function:
|
55
|
+
1. Perturbs the parameter up and down by a small displacement
|
56
|
+
2. Calculates steady states for each perturbation
|
57
|
+
3. Computes response coefficients from the differences
|
58
|
+
4. Optionally normalizes the results
|
59
|
+
|
60
|
+
Args:
|
61
|
+
parameter: Name of the parameter to analyze
|
62
|
+
model: Metabolic model instance
|
63
|
+
y0: Initial conditions as a dictionary {species: value}
|
64
|
+
normalized: Whether to normalize the coefficients
|
65
|
+
rel_norm: Whether to use relative normalization
|
66
|
+
displacement: Relative perturbation size (default: 1e-4)
|
67
|
+
integrator: Integrator function to use for steady state calculation
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
tuple[pd.Series, pd.Series]: Tuple containing:
|
71
|
+
- Series of concentration response coefficients
|
72
|
+
- Series of flux response coefficients
|
73
|
+
|
74
|
+
"""
|
75
|
+
old = model.parameters[parameter]
|
76
|
+
if y0 is not None:
|
77
|
+
model.update_variables(y0)
|
78
|
+
|
79
|
+
model.update_parameters({parameter: old * (1 + displacement)})
|
80
|
+
upper = _steady_state_worker(
|
81
|
+
model,
|
82
|
+
rel_norm=rel_norm,
|
83
|
+
integrator=integrator,
|
84
|
+
)
|
85
|
+
|
86
|
+
model.update_parameters({parameter: old * (1 - displacement)})
|
87
|
+
lower = _steady_state_worker(
|
88
|
+
model,
|
89
|
+
rel_norm=rel_norm,
|
90
|
+
integrator=integrator,
|
91
|
+
)
|
92
|
+
|
93
|
+
conc_resp = (upper.variables - lower.variables) / (2 * displacement * old)
|
94
|
+
flux_resp = (upper.fluxes - lower.fluxes) / (2 * displacement * old)
|
95
|
+
# Reset
|
96
|
+
model.update_parameters({parameter: old})
|
97
|
+
if normalized:
|
98
|
+
norm = _steady_state_worker(
|
99
|
+
model,
|
100
|
+
rel_norm=rel_norm,
|
101
|
+
integrator=integrator,
|
102
|
+
)
|
103
|
+
conc_resp *= old / norm.variables
|
104
|
+
flux_resp *= old / norm.fluxes
|
105
|
+
return conc_resp, flux_resp
|
106
|
+
|
107
|
+
|
41
108
|
###############################################################################
|
42
109
|
# Non-steady state
|
43
110
|
###############################################################################
|
@@ -46,8 +113,8 @@ if TYPE_CHECKING:
|
|
46
113
|
def variable_elasticities(
|
47
114
|
model: Model,
|
48
115
|
*,
|
49
|
-
|
50
|
-
variables:
|
116
|
+
to_scan: list[str] | None = None,
|
117
|
+
variables: dict[str, float] | None = None,
|
51
118
|
time: float = 0,
|
52
119
|
normalized: bool = True,
|
53
120
|
displacement: float = 1e-4,
|
@@ -67,8 +134,8 @@ def variable_elasticities(
|
|
67
134
|
|
68
135
|
Args:
|
69
136
|
model: Metabolic model instance
|
70
|
-
|
71
|
-
variables:
|
137
|
+
to_scan: List of variables to analyze. Uses all if None
|
138
|
+
variables: Custom variable values. Defaults to initial conditions.
|
72
139
|
time: Time point for evaluation
|
73
140
|
normalized: Whether to normalize coefficients
|
74
141
|
displacement: Relative perturbation size
|
@@ -77,23 +144,23 @@ def variable_elasticities(
|
|
77
144
|
DataFrame with elasticity coefficients (reactions x metabolites)
|
78
145
|
|
79
146
|
"""
|
80
|
-
|
81
|
-
|
147
|
+
variables = model.get_initial_conditions() if variables is None else variables
|
148
|
+
to_scan = model.get_variable_names() if to_scan is None else to_scan
|
82
149
|
elasticities = {}
|
83
150
|
|
84
|
-
for var in
|
85
|
-
old =
|
151
|
+
for var in to_scan:
|
152
|
+
old = variables[var]
|
86
153
|
|
87
154
|
upper = model.get_fluxes(
|
88
|
-
variables=
|
155
|
+
variables=variables | {var: old * (1 + displacement)}, time=time
|
89
156
|
)
|
90
157
|
lower = model.get_fluxes(
|
91
|
-
variables=
|
158
|
+
variables=variables | {var: old * (1 - displacement)}, time=time
|
92
159
|
)
|
93
160
|
|
94
161
|
elasticity_coef = (upper - lower) / (2 * displacement * old)
|
95
162
|
if normalized:
|
96
|
-
elasticity_coef *= old / model.get_fluxes(variables=
|
163
|
+
elasticity_coef *= old / model.get_fluxes(variables=variables, time=time)
|
97
164
|
elasticities[var] = elasticity_coef
|
98
165
|
|
99
166
|
return pd.DataFrame(data=elasticities)
|
@@ -101,10 +168,10 @@ def variable_elasticities(
|
|
101
168
|
|
102
169
|
def parameter_elasticities(
|
103
170
|
model: Model,
|
104
|
-
parameters: list[str] | None = None,
|
105
|
-
concs: dict[str, float] | None = None,
|
106
|
-
time: float = 0,
|
107
171
|
*,
|
172
|
+
to_scan: list[str] | None = None,
|
173
|
+
variables: dict[str, float] | None = None,
|
174
|
+
time: float = 0,
|
108
175
|
normalized: bool = True,
|
109
176
|
displacement: float = 1e-4,
|
110
177
|
) -> pd.DataFrame:
|
@@ -119,8 +186,8 @@ def parameter_elasticities(
|
|
119
186
|
|
120
187
|
Args:
|
121
188
|
model: Metabolic model instance
|
122
|
-
|
123
|
-
|
189
|
+
to_scan: List of parameters to analyze. Uses all if None
|
190
|
+
variables: Custom variable values. Defaults to initial conditions.
|
124
191
|
time: Time point for evaluation
|
125
192
|
normalized: Whether to normalize coefficients
|
126
193
|
displacement: Relative perturbation size
|
@@ -129,26 +196,26 @@ def parameter_elasticities(
|
|
129
196
|
DataFrame with parameter elasticities (reactions x parameters)
|
130
197
|
|
131
198
|
"""
|
132
|
-
|
133
|
-
|
199
|
+
variables = model.get_initial_conditions() if variables is None else variables
|
200
|
+
to_scan = model.get_parameter_names() if to_scan is None else to_scan
|
134
201
|
|
135
202
|
elasticities = {}
|
136
203
|
|
137
|
-
|
138
|
-
for par in
|
204
|
+
variables = model.get_initial_conditions() if variables is None else variables
|
205
|
+
for par in to_scan:
|
139
206
|
old = model.parameters[par]
|
140
207
|
|
141
208
|
model.update_parameters({par: old * (1 + displacement)})
|
142
|
-
upper = model.get_fluxes(variables=
|
209
|
+
upper = model.get_fluxes(variables=variables, time=time)
|
143
210
|
|
144
211
|
model.update_parameters({par: old * (1 - displacement)})
|
145
|
-
lower = model.get_fluxes(variables=
|
212
|
+
lower = model.get_fluxes(variables=variables, time=time)
|
146
213
|
|
147
214
|
# Reset
|
148
215
|
model.update_parameters({par: old})
|
149
216
|
elasticity_coef = (upper - lower) / (2 * displacement * old)
|
150
217
|
if normalized:
|
151
|
-
elasticity_coef *= old / model.get_fluxes(variables=
|
218
|
+
elasticity_coef *= old / model.get_fluxes(variables=variables, time=time)
|
152
219
|
elasticities[par] = elasticity_coef
|
153
220
|
|
154
221
|
return pd.DataFrame(data=elasticities)
|
@@ -159,79 +226,11 @@ def parameter_elasticities(
|
|
159
226
|
# ###############################################################################
|
160
227
|
|
161
228
|
|
162
|
-
def _response_coefficient_worker(
|
163
|
-
parameter: str,
|
164
|
-
*,
|
165
|
-
model: Model,
|
166
|
-
y0: dict[str, float] | None,
|
167
|
-
normalized: bool,
|
168
|
-
rel_norm: bool,
|
169
|
-
displacement: float = 1e-4,
|
170
|
-
integrator: IntegratorType,
|
171
|
-
) -> tuple[pd.Series, pd.Series]:
|
172
|
-
"""Calculate response coefficients for a single parameter.
|
173
|
-
|
174
|
-
Internal helper function that computes concentration and flux response
|
175
|
-
coefficients using finite differences. The function:
|
176
|
-
1. Perturbs the parameter up and down by a small displacement
|
177
|
-
2. Calculates steady states for each perturbation
|
178
|
-
3. Computes response coefficients from the differences
|
179
|
-
4. Optionally normalizes the results
|
180
|
-
|
181
|
-
Args:
|
182
|
-
parameter: Name of the parameter to analyze
|
183
|
-
model: Metabolic model instance
|
184
|
-
y0: Initial conditions as a dictionary {species: value}
|
185
|
-
normalized: Whether to normalize the coefficients
|
186
|
-
rel_norm: Whether to use relative normalization
|
187
|
-
displacement: Relative perturbation size (default: 1e-4)
|
188
|
-
integrator: Integrator function to use for steady state calculation
|
189
|
-
|
190
|
-
Returns:
|
191
|
-
tuple[pd.Series, pd.Series]: Tuple containing:
|
192
|
-
- Series of concentration response coefficients
|
193
|
-
- Series of flux response coefficients
|
194
|
-
|
195
|
-
"""
|
196
|
-
old = model.parameters[parameter]
|
197
|
-
|
198
|
-
model.update_parameters({parameter: old * (1 + displacement)})
|
199
|
-
upper = _steady_state_worker(
|
200
|
-
model,
|
201
|
-
y0=y0,
|
202
|
-
rel_norm=rel_norm,
|
203
|
-
integrator=integrator,
|
204
|
-
)
|
205
|
-
|
206
|
-
model.update_parameters({parameter: old * (1 - displacement)})
|
207
|
-
lower = _steady_state_worker(
|
208
|
-
model,
|
209
|
-
y0=y0,
|
210
|
-
rel_norm=rel_norm,
|
211
|
-
integrator=integrator,
|
212
|
-
)
|
213
|
-
|
214
|
-
conc_resp = (upper.variables - lower.variables) / (2 * displacement * old)
|
215
|
-
flux_resp = (upper.fluxes - lower.fluxes) / (2 * displacement * old)
|
216
|
-
# Reset
|
217
|
-
model.update_parameters({parameter: old})
|
218
|
-
if normalized:
|
219
|
-
norm = _steady_state_worker(
|
220
|
-
model,
|
221
|
-
y0=y0,
|
222
|
-
rel_norm=rel_norm,
|
223
|
-
integrator=integrator,
|
224
|
-
)
|
225
|
-
conc_resp *= old / norm.variables
|
226
|
-
flux_resp *= old / norm.fluxes
|
227
|
-
return conc_resp, flux_resp
|
228
|
-
|
229
|
-
|
230
229
|
def response_coefficients(
|
231
230
|
model: Model,
|
232
|
-
parameters: list[str] | None = None,
|
233
231
|
*,
|
234
|
-
|
232
|
+
to_scan: list[str] | None = None,
|
233
|
+
variables: dict[str, float] | None = None,
|
235
234
|
normalized: bool = True,
|
236
235
|
displacement: float = 1e-4,
|
237
236
|
disable_tqdm: bool = False,
|
@@ -250,8 +249,8 @@ def response_coefficients(
|
|
250
249
|
|
251
250
|
Args:
|
252
251
|
model: Metabolic model instance
|
253
|
-
|
254
|
-
|
252
|
+
to_scan: Parameters to analyze. Uses all if None
|
253
|
+
variables: Custom variable values. Defaults to initial conditions.
|
255
254
|
normalized: Whether to normalize coefficients
|
256
255
|
displacement: Relative perturbation size
|
257
256
|
disable_tqdm: Disable progress bar
|
@@ -266,19 +265,19 @@ def response_coefficients(
|
|
266
265
|
- Concentration response coefficients
|
267
266
|
|
268
267
|
"""
|
269
|
-
|
268
|
+
to_scan = model.get_parameter_names() if to_scan is None else to_scan
|
270
269
|
|
271
270
|
res = parallelise(
|
272
271
|
partial(
|
273
272
|
_response_coefficient_worker,
|
274
273
|
model=model,
|
275
|
-
y0=
|
274
|
+
y0=variables,
|
276
275
|
normalized=normalized,
|
277
276
|
displacement=displacement,
|
278
277
|
rel_norm=rel_norm,
|
279
278
|
integrator=integrator,
|
280
279
|
),
|
281
|
-
inputs=list(zip(
|
280
|
+
inputs=list(zip(to_scan, to_scan, strict=True)),
|
282
281
|
cache=None,
|
283
282
|
disable_tqdm=disable_tqdm,
|
284
283
|
parallel=parallel,
|
mxlpy/meta/codegen_latex.py
CHANGED
@@ -37,7 +37,26 @@ def _list_of_symbols(args: list[str]) -> list[sympy.Symbol | sympy.Expr]:
|
|
37
37
|
|
38
38
|
|
39
39
|
def default_init[T1, T2](d: dict[T1, T2] | None) -> dict[T1, T2]:
|
40
|
-
"""Return empty dict if d is None.
|
40
|
+
"""Return empty dict if d is None.
|
41
|
+
|
42
|
+
Parameters
|
43
|
+
----------
|
44
|
+
d
|
45
|
+
Dictionary to check
|
46
|
+
|
47
|
+
Returns
|
48
|
+
-------
|
49
|
+
dict
|
50
|
+
Original dictionary if not None, otherwise an empty dictionary
|
51
|
+
|
52
|
+
Examples
|
53
|
+
--------
|
54
|
+
>>> default_init(None)
|
55
|
+
{}
|
56
|
+
>>> default_init({"key": "value"})
|
57
|
+
{'key': 'value'}
|
58
|
+
|
59
|
+
"""
|
41
60
|
return {} if d is None else d
|
42
61
|
|
43
62
|
|
@@ -256,7 +275,23 @@ def _stoichiometries_to_latex(stoich: Mapping[str, float | Derived]) -> str:
|
|
256
275
|
|
257
276
|
@dataclass
|
258
277
|
class TexReaction:
|
259
|
-
"""Collection for reaction.
|
278
|
+
"""Collection for reaction.
|
279
|
+
|
280
|
+
Parameters
|
281
|
+
----------
|
282
|
+
fn
|
283
|
+
Rate function for the reaction
|
284
|
+
args
|
285
|
+
List of argument names for the rate function
|
286
|
+
|
287
|
+
Examples
|
288
|
+
--------
|
289
|
+
>>> def rate_fn(k, s): return k * s
|
290
|
+
>>> reaction = TexReaction(fn=rate_fn, args=["k1", "S"])
|
291
|
+
>>> reaction.fn(0.1, 1.0)
|
292
|
+
0.1
|
293
|
+
|
294
|
+
"""
|
260
295
|
|
261
296
|
fn: RateFn
|
262
297
|
args: list[str]
|
@@ -264,7 +299,35 @@ class TexReaction:
|
|
264
299
|
|
265
300
|
@dataclass
|
266
301
|
class TexExport:
|
267
|
-
"""Container for LaTeX export.
|
302
|
+
"""Container for LaTeX export.
|
303
|
+
|
304
|
+
This class handles the conversion of model components to LaTeX format
|
305
|
+
for exporting models as LaTeX documents.
|
306
|
+
|
307
|
+
Parameters
|
308
|
+
----------
|
309
|
+
parameters
|
310
|
+
Dictionary of parameter names and their values
|
311
|
+
variables
|
312
|
+
Dictionary of variable names and their initial values
|
313
|
+
derived
|
314
|
+
Dictionary of derived variables and their definitions
|
315
|
+
reactions
|
316
|
+
Dictionary of reaction names and their rate functions
|
317
|
+
stoichiometries
|
318
|
+
Dictionary mapping reaction names to stoichiometry dictionaries
|
319
|
+
|
320
|
+
Examples
|
321
|
+
--------
|
322
|
+
>>> parameters = {"k1": 0.1, "k2": 0.2}
|
323
|
+
>>> variables = {"S": 1.0, "P": 0.0}
|
324
|
+
>>> derived = {"total": Derived(fn=lambda s, p: s + p, args=["S", "P"])}
|
325
|
+
>>> reactions = {"v1": TexReaction(fn=lambda k, s: k*s, args=["k1", "S"])}
|
326
|
+
>>> stoich = {"v1": {"S": -1, "P": 1}}
|
327
|
+
>>> tex = TexExport(parameters, variables, derived, reactions, stoich)
|
328
|
+
>>> latex_doc = tex.export_document(author="User", title="My Model")
|
329
|
+
|
330
|
+
"""
|
268
331
|
|
269
332
|
parameters: dict[str, float]
|
270
333
|
variables: dict[str, float]
|
@@ -298,7 +361,27 @@ class TexExport:
|
|
298
361
|
return {k: v for k, v in p2.items() if k not in p1 or p1[k] != v}
|
299
362
|
|
300
363
|
def __sub__(self, other: object) -> TexExport:
|
301
|
-
"""Return difference of two tex exports.
|
364
|
+
"""Return difference of two tex exports.
|
365
|
+
|
366
|
+
Parameters
|
367
|
+
----------
|
368
|
+
other
|
369
|
+
Another TexExport instance to compare with
|
370
|
+
|
371
|
+
Returns
|
372
|
+
-------
|
373
|
+
TexExport
|
374
|
+
A new TexExport containing only the elements that differ
|
375
|
+
|
376
|
+
Examples
|
377
|
+
--------
|
378
|
+
>>> tex1 = TexExport({"k": 1.0}, {}, {}, {}, {})
|
379
|
+
>>> tex2 = TexExport({"k": 2.0}, {}, {}, {}, {})
|
380
|
+
>>> diff = tex1 - tex2
|
381
|
+
>>> diff.parameters
|
382
|
+
{'k': 2.0}
|
383
|
+
|
384
|
+
"""
|
302
385
|
if not isinstance(other, TexExport):
|
303
386
|
raise TypeError
|
304
387
|
|
@@ -315,7 +398,28 @@ class TexExport:
|
|
315
398
|
)
|
316
399
|
|
317
400
|
def rename_with_glossary(self, gls: dict[str, str]) -> TexExport:
|
318
|
-
"""Rename all elements according to glossary.
|
401
|
+
"""Rename all elements according to glossary.
|
402
|
+
|
403
|
+
Parameters
|
404
|
+
----------
|
405
|
+
gls
|
406
|
+
Dictionary mapping original names to glossary names
|
407
|
+
|
408
|
+
Returns
|
409
|
+
-------
|
410
|
+
TexExport
|
411
|
+
A new TexExport with renamed elements
|
412
|
+
|
413
|
+
Examples
|
414
|
+
--------
|
415
|
+
>>> tex = TexExport({"k": 1.0}, {"S": 1.0}, {}, {}, {})
|
416
|
+
>>> renamed = tex.rename_with_glossary({"k": "rate", "S": "substrate"})
|
417
|
+
>>> renamed.parameters
|
418
|
+
{'rate': 1.0}
|
419
|
+
>>> renamed.variables
|
420
|
+
{'substrate': 1.0}
|
421
|
+
|
422
|
+
"""
|
319
423
|
|
320
424
|
def _add_gls_if_found(k: str) -> str:
|
321
425
|
if (new := gls.get(k)) is not None:
|
@@ -343,7 +447,21 @@ class TexExport:
|
|
343
447
|
)
|
344
448
|
|
345
449
|
def export_variables(self) -> str:
|
346
|
-
"""Export variables.
|
450
|
+
"""Export variables as LaTeX table.
|
451
|
+
|
452
|
+
Returns
|
453
|
+
-------
|
454
|
+
str
|
455
|
+
LaTeX code for variables table
|
456
|
+
|
457
|
+
Examples
|
458
|
+
--------
|
459
|
+
>>> tex = TexExport({}, {"S": 1.0, "P": 0.5}, {}, {}, {})
|
460
|
+
>>> latex = tex.export_variables()
|
461
|
+
>>> "Model variables" in latex
|
462
|
+
True
|
463
|
+
|
464
|
+
"""
|
347
465
|
return _table(
|
348
466
|
headers=["Model name", "Initial concentration"],
|
349
467
|
rows=[
|
@@ -360,7 +478,21 @@ class TexExport:
|
|
360
478
|
)
|
361
479
|
|
362
480
|
def export_parameters(self) -> str:
|
363
|
-
"""Export parameters.
|
481
|
+
"""Export parameters as LaTeX table.
|
482
|
+
|
483
|
+
Returns
|
484
|
+
-------
|
485
|
+
str
|
486
|
+
LaTeX code for parameters table
|
487
|
+
|
488
|
+
Examples
|
489
|
+
--------
|
490
|
+
>>> tex = TexExport({"k1": 0.1, "k2": 0.2}, {}, {}, {}, {})
|
491
|
+
>>> latex = tex.export_parameters()
|
492
|
+
>>> "Model parameters" in latex
|
493
|
+
True
|
494
|
+
|
495
|
+
"""
|
364
496
|
return _table(
|
365
497
|
headers=["Parameter name", "Parameter value"],
|
366
498
|
rows=[
|
@@ -374,7 +506,23 @@ class TexExport:
|
|
374
506
|
)
|
375
507
|
|
376
508
|
def export_derived(self) -> str:
|
377
|
-
"""Export derived quantities.
|
509
|
+
"""Export derived quantities as LaTeX equations.
|
510
|
+
|
511
|
+
Returns
|
512
|
+
-------
|
513
|
+
str
|
514
|
+
LaTeX code with derived quantity equations
|
515
|
+
|
516
|
+
Examples
|
517
|
+
--------
|
518
|
+
>>> def sum_fn(x, y): return x + y
|
519
|
+
>>> derived = {"total": Derived(fn=sum_fn, args=["S", "P"])}
|
520
|
+
>>> tex = TexExport({}, {}, derived, {}, {})
|
521
|
+
>>> latex = tex.export_derived()
|
522
|
+
>>> "total" in latex
|
523
|
+
True
|
524
|
+
|
525
|
+
"""
|
378
526
|
return _latex_list(
|
379
527
|
rows=[
|
380
528
|
_dmath(
|
@@ -385,7 +533,23 @@ class TexExport:
|
|
385
533
|
)
|
386
534
|
|
387
535
|
def export_reactions(self) -> str:
|
388
|
-
"""Export reactions.
|
536
|
+
"""Export reactions as LaTeX equations.
|
537
|
+
|
538
|
+
Returns
|
539
|
+
-------
|
540
|
+
str
|
541
|
+
LaTeX code with reaction rate equations
|
542
|
+
|
543
|
+
Examples
|
544
|
+
--------
|
545
|
+
>>> def rate_fn(k, s): return k * s
|
546
|
+
>>> reactions = {"v1": TexReaction(fn=rate_fn, args=["k1", "S"])}
|
547
|
+
>>> tex = TexExport({}, {}, {}, reactions, {})
|
548
|
+
>>> latex = tex.export_reactions()
|
549
|
+
>>> "v1" in latex
|
550
|
+
True
|
551
|
+
|
552
|
+
"""
|
389
553
|
return _latex_list(
|
390
554
|
rows=[
|
391
555
|
_dmath(
|
@@ -396,7 +560,22 @@ class TexExport:
|
|
396
560
|
)
|
397
561
|
|
398
562
|
def export_stoichiometries(self) -> str:
|
399
|
-
"""Export stoichiometries.
|
563
|
+
"""Export stoichiometries as LaTeX table.
|
564
|
+
|
565
|
+
Returns
|
566
|
+
-------
|
567
|
+
str
|
568
|
+
LaTeX code for stoichiometries table
|
569
|
+
|
570
|
+
Examples
|
571
|
+
--------
|
572
|
+
>>> stoich = {"v1": {"S": -1, "P": 1}}
|
573
|
+
>>> tex = TexExport({}, {}, {}, {}, stoich)
|
574
|
+
>>> latex = tex.export_stoichiometries()
|
575
|
+
>>> "Model stoichiometries" in latex
|
576
|
+
True
|
577
|
+
|
578
|
+
"""
|
400
579
|
return _table(
|
401
580
|
headers=["Rate name", "Stoichiometry"],
|
402
581
|
rows=[
|
@@ -413,7 +592,21 @@ class TexExport:
|
|
413
592
|
)
|
414
593
|
|
415
594
|
def export_all(self) -> str:
|
416
|
-
"""Export all model parts.
|
595
|
+
"""Export all model parts as a complete LaTeX document section.
|
596
|
+
|
597
|
+
Returns
|
598
|
+
-------
|
599
|
+
str
|
600
|
+
LaTeX code containing all model components
|
601
|
+
|
602
|
+
Examples
|
603
|
+
--------
|
604
|
+
>>> tex = TexExport({"k": 1.0}, {"S": 1.0}, {}, {}, {})
|
605
|
+
>>> latex = tex.export_all()
|
606
|
+
>>> "Parameters" in latex and "Variables" in latex
|
607
|
+
True
|
608
|
+
|
609
|
+
"""
|
417
610
|
sections = []
|
418
611
|
if len(self.variables) > 0:
|
419
612
|
sections.append(
|
@@ -456,7 +649,28 @@ class TexExport:
|
|
456
649
|
author: str = "mxlpy",
|
457
650
|
title: str = "Model construction",
|
458
651
|
) -> str:
|
459
|
-
"""Export
|
652
|
+
r"""Export complete LaTeX document with all model components.
|
653
|
+
|
654
|
+
Parameters
|
655
|
+
----------
|
656
|
+
author
|
657
|
+
Name of the author for the document
|
658
|
+
title
|
659
|
+
Title for the document
|
660
|
+
|
661
|
+
Returns
|
662
|
+
-------
|
663
|
+
str
|
664
|
+
Complete LaTeX document as a string
|
665
|
+
|
666
|
+
Examples
|
667
|
+
--------
|
668
|
+
>>> tex = TexExport({"k": 1.0}, {"S": 1.0}, {}, {}, {})
|
669
|
+
>>> doc = tex.export_document(author="Jane Doe", title="My Model")
|
670
|
+
>>> "\\title{My Model}" in doc and "\\author{Jane Doe}" in doc
|
671
|
+
True
|
672
|
+
|
673
|
+
"""
|
460
674
|
content = self.export_all()
|
461
675
|
return rf"""\documentclass{{article}}
|
462
676
|
\usepackage[english]{{babel}}
|
@@ -491,7 +705,33 @@ def generate_latex_code(
|
|
491
705
|
model: Model,
|
492
706
|
gls: dict[str, str] | None = None,
|
493
707
|
) -> str:
|
494
|
-
"""Export as LaTeX.
|
708
|
+
"""Export model as LaTeX document.
|
709
|
+
|
710
|
+
Parameters
|
711
|
+
----------
|
712
|
+
model
|
713
|
+
The model to export
|
714
|
+
gls
|
715
|
+
Optional glossary mapping for renaming model components
|
716
|
+
|
717
|
+
Returns
|
718
|
+
-------
|
719
|
+
str
|
720
|
+
Complete LaTeX document as string
|
721
|
+
|
722
|
+
Examples
|
723
|
+
--------
|
724
|
+
>>> from mxlpy import Model
|
725
|
+
>>> model = Model()
|
726
|
+
>>> model.add_parameter("k1", 0.1)
|
727
|
+
>>> model.add_variable("S", 1.0)
|
728
|
+
>>> latex = generate_latex_code(model)
|
729
|
+
>>> "Model parameters" in latex and "Model variables" in latex
|
730
|
+
True
|
731
|
+
>>> # With glossary
|
732
|
+
>>> latex = generate_latex_code(model, {"k1": "rate", "S": "substrate"})
|
733
|
+
|
734
|
+
"""
|
495
735
|
gls = default_init(gls)
|
496
736
|
return _to_tex_export(model).rename_with_glossary(gls).export_document()
|
497
737
|
|
@@ -501,7 +741,32 @@ def get_model_tex_diff(
|
|
501
741
|
m2: Model,
|
502
742
|
gls: dict[str, str] | None = None,
|
503
743
|
) -> str:
|
504
|
-
"""Create LaTeX diff
|
744
|
+
"""Create LaTeX diff showing changes between two models.
|
745
|
+
|
746
|
+
Parameters
|
747
|
+
----------
|
748
|
+
m1
|
749
|
+
First model (considered as base model)
|
750
|
+
m2
|
751
|
+
Second model (compared against the base)
|
752
|
+
gls
|
753
|
+
Optional glossary mapping for renaming model components
|
754
|
+
|
755
|
+
Returns
|
756
|
+
-------
|
757
|
+
str
|
758
|
+
LaTeX document section showing differences between models
|
759
|
+
|
760
|
+
Examples
|
761
|
+
--------
|
762
|
+
>>> from mxlpy import Model
|
763
|
+
>>> m1 = Model().add_parameter("k1", 0.1)
|
764
|
+
>>> m2 = Model().add_parameter("k1", 0.2)
|
765
|
+
>>> diff = get_model_tex_diff(m1, m2)
|
766
|
+
>>> "Model changes" in diff and "Parameters" in diff
|
767
|
+
True
|
768
|
+
|
769
|
+
"""
|
505
770
|
gls = default_init(gls)
|
506
771
|
section_label = "sec:model-diff"
|
507
772
|
|