modelbase2 0.1.79__py3-none-any.whl → 0.2.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 (58) hide show
  1. modelbase2/__init__.py +138 -26
  2. modelbase2/distributions.py +306 -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/npe.py +343 -0
  19. modelbase2/parallel.py +171 -0
  20. modelbase2/parameterise.py +28 -0
  21. modelbase2/paths.py +36 -0
  22. modelbase2/plot.py +829 -0
  23. modelbase2/sbml/__init__.py +14 -0
  24. modelbase2/sbml/_data.py +77 -0
  25. modelbase2/sbml/_export.py +656 -0
  26. modelbase2/sbml/_import.py +585 -0
  27. modelbase2/sbml/_mathml.py +691 -0
  28. modelbase2/sbml/_name_conversion.py +52 -0
  29. modelbase2/sbml/_unit_conversion.py +74 -0
  30. modelbase2/scan.py +616 -0
  31. modelbase2/scope.py +96 -0
  32. modelbase2/simulator.py +635 -0
  33. modelbase2/surrogates/__init__.py +32 -0
  34. modelbase2/surrogates/_poly.py +66 -0
  35. modelbase2/surrogates/_torch.py +249 -0
  36. modelbase2/surrogates.py +316 -0
  37. modelbase2/types.py +352 -11
  38. modelbase2-0.2.0.dist-info/METADATA +81 -0
  39. modelbase2-0.2.0.dist-info/RECORD +42 -0
  40. {modelbase2-0.1.79.dist-info → modelbase2-0.2.0.dist-info}/WHEEL +1 -1
  41. modelbase2/core/__init__.py +0 -29
  42. modelbase2/core/algebraic_module_container.py +0 -130
  43. modelbase2/core/constant_container.py +0 -113
  44. modelbase2/core/data.py +0 -109
  45. modelbase2/core/name_container.py +0 -29
  46. modelbase2/core/reaction_container.py +0 -115
  47. modelbase2/core/utils.py +0 -28
  48. modelbase2/core/variable_container.py +0 -24
  49. modelbase2/ode/__init__.py +0 -13
  50. modelbase2/ode/integrator.py +0 -80
  51. modelbase2/ode/mca.py +0 -270
  52. modelbase2/ode/model.py +0 -470
  53. modelbase2/ode/simulator.py +0 -153
  54. modelbase2/utils/__init__.py +0 -0
  55. modelbase2/utils/plotting.py +0 -372
  56. modelbase2-0.1.79.dist-info/METADATA +0 -44
  57. modelbase2-0.1.79.dist-info/RECORD +0 -22
  58. {modelbase2-0.1.79.dist-info → modelbase2-0.2.0.dist-info/licenses}/LICENSE +0 -0
modelbase2/mca.py ADDED
@@ -0,0 +1,280 @@
1
+ """Metabolic Control Analysis (MCA) Module.
2
+
3
+ Provides functions for analyzing control and regulation in metabolic networks through:
4
+ - Elasticity coefficients (variable and parameter)
5
+ - Response coefficients
6
+
7
+ Main Functions:
8
+ variable_elasticities: Calculate non-steady state variable elasticities
9
+ parameter_elasticities: Calculate non-steady state parameter elasticities
10
+ response_coefficients: Calculate response coefficients for steady state
11
+
12
+ Mathematical Background:
13
+ MCA quantifies how changes in system parameters affect metabolic variables
14
+ through elasticity and control coefficients. These describe the sensitivity
15
+ of reaction rates and steady state variables to perturbations.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ from functools import partial
21
+ from typing import TYPE_CHECKING
22
+
23
+ import pandas as pd
24
+
25
+ from modelbase2.parallel import parallelise
26
+ from modelbase2.scan import _steady_state_worker
27
+ from modelbase2.types import ResponseCoefficients
28
+
29
+ __all__ = [
30
+ "parameter_elasticities",
31
+ "response_coefficients",
32
+ "variable_elasticities",
33
+ ]
34
+
35
+ if TYPE_CHECKING:
36
+ from modelbase2.model import Model
37
+
38
+
39
+ ###############################################################################
40
+ # Non-steady state
41
+ ###############################################################################
42
+
43
+
44
+ def variable_elasticities(
45
+ model: Model,
46
+ *,
47
+ concs: dict[str, float] | None = None,
48
+ variables: list[str] | None = None,
49
+ time: float = 0,
50
+ normalized: bool = True,
51
+ displacement: float = 1e-4,
52
+ ) -> pd.DataFrame:
53
+ """Calculate non-steady state elasticity coefficients.
54
+
55
+ Computes the sensitivity of reaction rates to changes in metabolite
56
+ concentrations (ε-elasticities).
57
+
58
+ Examples:
59
+ >>> variable_elasticities(model, concs={"A": 1.0, "B": 2.0})
60
+ Rxn A B
61
+ v1 0.0 0.0
62
+ v2 1.0 0.0
63
+ v3 0.0 5.0
64
+
65
+
66
+ Args:
67
+ model: Metabolic model instance
68
+ concs: Initial concentrations {metabolite: value}. Uses model defaults if None
69
+ variables: List of variables to analyze. Uses all if None
70
+ time: Time point for evaluation
71
+ normalized: Whether to normalize coefficients
72
+ displacement: Relative perturbation size
73
+
74
+ Returns:
75
+ DataFrame with elasticity coefficients (reactions x metabolites)
76
+
77
+ """
78
+ concs = model.get_initial_conditions() if concs is None else concs
79
+ variables = model.get_variable_names() if variables is None else variables
80
+ elasticities = {}
81
+
82
+ for var in variables:
83
+ old = concs[var]
84
+
85
+ upper = model.get_fluxes(
86
+ concs=concs | {var: old * (1 + displacement)}, time=time
87
+ )
88
+ lower = model.get_fluxes(
89
+ concs=concs | {var: old * (1 - displacement)}, time=time
90
+ )
91
+
92
+ elasticity_coef = (upper - lower) / (2 * displacement * old)
93
+ if normalized:
94
+ elasticity_coef *= old / model.get_fluxes(concs=concs, time=time)
95
+ elasticities[var] = elasticity_coef
96
+
97
+ return pd.DataFrame(data=elasticities)
98
+
99
+
100
+ def parameter_elasticities(
101
+ model: Model,
102
+ parameters: list[str] | None = None,
103
+ concs: dict[str, float] | None = None,
104
+ time: float = 0,
105
+ *,
106
+ normalized: bool = True,
107
+ displacement: float = 1e-4,
108
+ ) -> pd.DataFrame:
109
+ """Calculate parameter elasticity coefficients.
110
+
111
+ Examples:
112
+ >>> parameter_elasticities(model)
113
+ Rxn k1 k2
114
+ v1 1.0 0.0
115
+ v2 0.0 1.0
116
+ v3 0.0 0.0
117
+
118
+ Args:
119
+ model: Metabolic model instance
120
+ parameters: List of parameters to analyze. Uses all if None
121
+ concs: Initial concentrations {metabolite: value}. Uses model defaults if None
122
+ time: Time point for evaluation
123
+ normalized: Whether to normalize coefficients
124
+ displacement: Relative perturbation size
125
+
126
+ Returns:
127
+ DataFrame with parameter elasticities (reactions x parameters)
128
+
129
+ """
130
+ concs = model.get_initial_conditions() if concs is None else concs
131
+ parameters = model.get_parameter_names() if parameters is None else parameters
132
+
133
+ elasticities = {}
134
+
135
+ concs = model.get_initial_conditions() if concs is None else concs
136
+ for par in parameters:
137
+ old = model.parameters[par]
138
+
139
+ model.update_parameters({par: old * (1 + displacement)})
140
+ upper = model.get_fluxes(concs=concs, time=time)
141
+
142
+ model.update_parameters({par: old * (1 - displacement)})
143
+ lower = model.get_fluxes(concs=concs, time=time)
144
+
145
+ # Reset
146
+ model.update_parameters({par: old})
147
+ elasticity_coef = (upper - lower) / (2 * displacement * old)
148
+ if normalized:
149
+ elasticity_coef *= old / model.get_fluxes(concs=concs, time=time)
150
+ elasticities[par] = elasticity_coef
151
+
152
+ return pd.DataFrame(data=elasticities)
153
+
154
+
155
+ # ###############################################################################
156
+ # # Steady state
157
+ # ###############################################################################
158
+
159
+
160
+ def _response_coefficient_worker(
161
+ parameter: str,
162
+ *,
163
+ model: Model,
164
+ y0: dict[str, float] | None,
165
+ normalized: bool,
166
+ rel_norm: bool,
167
+ displacement: float = 1e-4,
168
+ ) -> tuple[pd.Series, pd.Series]:
169
+ """Calculate response coefficients for a single parameter.
170
+
171
+ Internal helper function that computes concentration and flux response
172
+ coefficients using finite differences. The function:
173
+ 1. Perturbs the parameter up and down by a small displacement
174
+ 2. Calculates steady states for each perturbation
175
+ 3. Computes response coefficients from the differences
176
+ 4. Optionally normalizes the results
177
+
178
+ Args:
179
+ parameter: Name of the parameter to analyze
180
+ model: Metabolic model instance
181
+ y0: Initial conditions as a dictionary {species: value}
182
+ normalized: Whether to normalize the coefficients
183
+ rel_norm: Whether to use relative normalization
184
+ displacement: Relative perturbation size (default: 1e-4)
185
+
186
+ Returns:
187
+ tuple[pd.Series, pd.Series]: Tuple containing:
188
+ - Series of concentration response coefficients
189
+ - Series of flux response coefficients
190
+
191
+ """
192
+ old = model.parameters[parameter]
193
+
194
+ model.update_parameters({parameter: old * (1 + displacement)})
195
+ upper = _steady_state_worker(
196
+ model,
197
+ y0=y0,
198
+ rel_norm=rel_norm,
199
+ )
200
+
201
+ model.update_parameters({parameter: old * (1 - displacement)})
202
+ lower = _steady_state_worker(
203
+ model,
204
+ y0=y0,
205
+ rel_norm=rel_norm,
206
+ )
207
+
208
+ conc_resp = (upper.concs - lower.concs) / (2 * displacement * old)
209
+ flux_resp = (upper.fluxes - lower.fluxes) / (2 * displacement * old)
210
+ # Reset
211
+ model.update_parameters({parameter: old})
212
+ if normalized:
213
+ norm = _steady_state_worker(
214
+ model,
215
+ y0=y0,
216
+ rel_norm=rel_norm,
217
+ )
218
+ conc_resp *= old / norm.concs
219
+ flux_resp *= old / norm.fluxes
220
+ return conc_resp, flux_resp
221
+
222
+
223
+ def response_coefficients(
224
+ model: Model,
225
+ parameters: list[str] | None = None,
226
+ *,
227
+ y0: dict[str, float] | None = None,
228
+ normalized: bool = True,
229
+ displacement: float = 1e-4,
230
+ disable_tqdm: bool = False,
231
+ parallel: bool = True,
232
+ max_workers: int | None = None,
233
+ rel_norm: bool = False,
234
+ ) -> ResponseCoefficients:
235
+ """Calculate response coefficients.
236
+
237
+ Examples:
238
+ >>> response_coefficients(model, parameters=["k1", "k2"]).concs
239
+ p x1 x2
240
+ k1 1.4 1.31
241
+ k2 -1.0 -2.49
242
+
243
+ Args:
244
+ model: Metabolic model instance
245
+ parameters: Parameters to analyze. Uses all if None
246
+ y0: Initial conditions as a dictionary {species: value}
247
+ normalized: Whether to normalize coefficients
248
+ displacement: Relative perturbation size
249
+ disable_tqdm: Disable progress bar
250
+ parallel: Whether to parallelize the computation
251
+ max_workers: Maximum number of workers
252
+ rel_norm: Whether to use relative normalization
253
+
254
+ Returns:
255
+ ResponseCoefficients object containing:
256
+ - Flux response coefficients
257
+ - Concentration response coefficients
258
+
259
+ """
260
+ parameters = model.get_parameter_names() if parameters is None else parameters
261
+
262
+ res = parallelise(
263
+ partial(
264
+ _response_coefficient_worker,
265
+ model=model,
266
+ y0=y0,
267
+ normalized=normalized,
268
+ displacement=displacement,
269
+ rel_norm=rel_norm,
270
+ ),
271
+ inputs=list(zip(parameters, parameters, strict=True)),
272
+ cache=None,
273
+ disable_tqdm=disable_tqdm,
274
+ parallel=parallel,
275
+ max_workers=max_workers,
276
+ )
277
+ return ResponseCoefficients(
278
+ concs=pd.DataFrame({k: v[0] for k, v in res.items()}),
279
+ fluxes=pd.DataFrame({k: v[1] for k, v in res.items()}),
280
+ )