mxlpy 0.18.0__py3-none-any.whl → 0.20.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 (51) hide show
  1. mxlpy/__init__.py +13 -9
  2. mxlpy/compare.py +240 -0
  3. mxlpy/experimental/diff.py +16 -4
  4. mxlpy/fit.py +6 -11
  5. mxlpy/fns.py +37 -42
  6. mxlpy/identify.py +10 -3
  7. mxlpy/integrators/__init__.py +4 -3
  8. mxlpy/integrators/int_assimulo.py +16 -9
  9. mxlpy/integrators/int_scipy.py +13 -9
  10. mxlpy/label_map.py +7 -3
  11. mxlpy/linear_label_map.py +4 -2
  12. mxlpy/mc.py +5 -14
  13. mxlpy/mca.py +4 -4
  14. mxlpy/meta/__init__.py +6 -4
  15. mxlpy/meta/codegen_latex.py +180 -87
  16. mxlpy/meta/codegen_modebase.py +3 -1
  17. mxlpy/meta/codegen_py.py +11 -3
  18. mxlpy/meta/source_tools.py +9 -5
  19. mxlpy/model.py +187 -100
  20. mxlpy/nn/__init__.py +24 -5
  21. mxlpy/nn/_keras.py +92 -0
  22. mxlpy/nn/_torch.py +25 -18
  23. mxlpy/npe/__init__.py +21 -16
  24. mxlpy/npe/_keras.py +326 -0
  25. mxlpy/npe/_torch.py +56 -60
  26. mxlpy/parallel.py +5 -2
  27. mxlpy/parameterise.py +11 -3
  28. mxlpy/plot.py +205 -52
  29. mxlpy/report.py +33 -8
  30. mxlpy/sbml/__init__.py +3 -3
  31. mxlpy/sbml/_data.py +7 -6
  32. mxlpy/sbml/_export.py +8 -1
  33. mxlpy/sbml/_mathml.py +8 -7
  34. mxlpy/sbml/_name_conversion.py +5 -1
  35. mxlpy/scan.py +14 -19
  36. mxlpy/simulator.py +34 -31
  37. mxlpy/surrogates/__init__.py +25 -17
  38. mxlpy/surrogates/_keras.py +139 -0
  39. mxlpy/surrogates/_poly.py +25 -10
  40. mxlpy/surrogates/_qss.py +34 -0
  41. mxlpy/surrogates/_torch.py +50 -32
  42. mxlpy/symbolic/__init__.py +5 -3
  43. mxlpy/symbolic/strikepy.py +5 -2
  44. mxlpy/symbolic/symbolic_model.py +14 -5
  45. mxlpy/types.py +61 -120
  46. {mxlpy-0.18.0.dist-info → mxlpy-0.20.0.dist-info}/METADATA +25 -24
  47. mxlpy-0.20.0.dist-info/RECORD +55 -0
  48. mxlpy/nn/_tensorflow.py +0 -0
  49. mxlpy-0.18.0.dist-info/RECORD +0 -51
  50. {mxlpy-0.18.0.dist-info → mxlpy-0.20.0.dist-info}/WHEEL +0 -0
  51. {mxlpy-0.18.0.dist-info → mxlpy-0.20.0.dist-info}/licenses/LICENSE +0 -0
mxlpy/__init__.py CHANGED
@@ -42,29 +42,23 @@ from typing import TYPE_CHECKING
42
42
  import pandas as pd
43
43
 
44
44
  from . import (
45
+ compare,
45
46
  distributions,
46
47
  experimental,
47
48
  fit,
48
49
  fns,
49
50
  mc,
50
51
  mca,
51
- npe,
52
52
  plot,
53
53
  report,
54
54
  sbml,
55
- surrogates,
56
55
  )
57
56
  from .integrators import DefaultIntegrator, Scipy
58
57
  from .label_map import LabelMapper
59
58
  from .linear_label_map import LinearLabelMapper
60
59
  from .mc import Cache
61
60
  from .model import Model
62
- from .nn import _torch
63
- from .scan import (
64
- steady_state,
65
- time_course,
66
- time_course_over_protocol,
67
- )
61
+ from .scan import steady_state, time_course, time_course_over_protocol
68
62
  from .simulator import Simulator
69
63
  from .symbolic import SymbolicModel, to_symbolic_model
70
64
  from .types import Derived, IntegratorProtocol, unwrap
@@ -75,6 +69,15 @@ with contextlib.suppress(ImportError):
75
69
  if TYPE_CHECKING:
76
70
  from mxlpy.types import ArrayLike
77
71
 
72
+ from . import nn, npe, surrogates
73
+ else:
74
+ from lazy_import import lazy_module
75
+
76
+ nn = lazy_module("mxlpy.nn")
77
+ npe = lazy_module("mxlpy.npe")
78
+ surrogates = lazy_module("mxlpy.surrogates")
79
+
80
+
78
81
  __all__ = [
79
82
  "Assimulo",
80
83
  "Cache",
@@ -87,8 +90,8 @@ __all__ = [
87
90
  "Scipy",
88
91
  "Simulator",
89
92
  "SymbolicModel",
90
- "_torch",
91
93
  "cartesian_product",
94
+ "compare",
92
95
  "distributions",
93
96
  "experimental",
94
97
  "fit",
@@ -96,6 +99,7 @@ __all__ = [
96
99
  "make_protocol",
97
100
  "mc",
98
101
  "mca",
102
+ "nn",
99
103
  "npe",
100
104
  "plot",
101
105
  "report",
mxlpy/compare.py ADDED
@@ -0,0 +1,240 @@
1
+ """Docstring."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import TYPE_CHECKING, cast
7
+
8
+ import pandas as pd
9
+
10
+ from mxlpy import plot
11
+ from mxlpy.simulator import Result, Simulator
12
+ from mxlpy.types import unwrap
13
+
14
+ if TYPE_CHECKING:
15
+ from mxlpy.model import Model
16
+ from mxlpy.types import ArrayLike
17
+
18
+ __all__ = [
19
+ "ProtocolComparison",
20
+ "SteadyStateComparison",
21
+ "TimeCourseComparison",
22
+ "protocol_time_courses",
23
+ "steady_states",
24
+ "time_courses",
25
+ ]
26
+
27
+
28
+ @dataclass
29
+ class SteadyStateComparison:
30
+ """Compare two steady states."""
31
+
32
+ res1: Result
33
+ res2: Result
34
+
35
+ @property
36
+ def variables(self) -> pd.DataFrame:
37
+ """Compare the steady state variables."""
38
+ ss1 = self.res1.get_variables().iloc[-1]
39
+ ss2 = self.res2.get_variables().iloc[-1]
40
+ diff = ss2 - ss1
41
+ return pd.DataFrame(
42
+ {"m1": ss1, "m2": ss2, "diff": diff, "rel_diff": diff / ss1}
43
+ )
44
+
45
+ @property
46
+ def fluxes(self) -> pd.DataFrame:
47
+ """Compare the steady state fluxes."""
48
+ ss1 = self.res1.get_fluxes().iloc[-1]
49
+ ss2 = self.res2.get_fluxes().iloc[-1]
50
+ diff = ss2 - ss1
51
+ return pd.DataFrame(
52
+ {"m1": ss1, "m2": ss2, "diff": diff, "rel_diff": diff / ss1}
53
+ )
54
+
55
+ @property
56
+ def all(self) -> pd.DataFrame:
57
+ """Compare both steady-state variables and fluxes."""
58
+ ss1 = self.res1.get_combined().iloc[-1]
59
+ ss2 = self.res2.get_combined().iloc[-1]
60
+ diff = ss2 - ss1
61
+ return pd.DataFrame(
62
+ {"m1": ss1, "m2": ss2, "diff": diff, "rel_diff": diff / ss1}
63
+ )
64
+
65
+ def plot_variables(self, title: str = "Variables") -> plot.FigAxs:
66
+ """Plot the relative difference of steady-state variables."""
67
+ fig, axs = plot.bars_autogrouped(self.variables["rel_diff"], ylabel="")
68
+ plot.grid_labels(axs, ylabel="Relative difference")
69
+ fig.suptitle(title)
70
+ return fig, axs
71
+
72
+ def plot_fluxes(self, title: str = "Fluxes") -> plot.FigAxs:
73
+ """Plot the relative difference of steady-state fluxes."""
74
+ fig, axs = plot.bars_autogrouped(self.fluxes["rel_diff"], ylabel="")
75
+ plot.grid_labels(axs, ylabel="Relative difference")
76
+ fig.suptitle(title)
77
+ return fig, axs
78
+
79
+ def plot_all(self, title: str = "Variables and Fluxes") -> plot.FigAxs:
80
+ """Plot the relative difference of steady-state variables and fluxes."""
81
+ combined = self.all
82
+
83
+ fig, axs = plot.bars_autogrouped(combined["rel_diff"], ylabel="")
84
+ plot.grid_labels(axs, ylabel="Relative difference")
85
+ fig.suptitle(title)
86
+ return fig, axs
87
+
88
+
89
+ @dataclass
90
+ class TimeCourseComparison:
91
+ """Compare two time courses."""
92
+
93
+ res1: Result
94
+ res2: Result
95
+
96
+ # @property
97
+ # def variables(self) -> pd.DataFrame:
98
+ # """Compare the steady state variables."""
99
+ # ss1 = self.res1.get_variables()
100
+ # ss2 = self.res2.get_variables()
101
+ # diff = ss2 - ss1
102
+ # return pd.DataFrame(
103
+ # {"m1": ss1, "m2": ss2, "diff": diff, "rel_diff": diff / ss1}
104
+ # )
105
+
106
+ # @property
107
+ # def fluxes(self) -> pd.DataFrame:
108
+ # """Compare the steady state fluxes."""
109
+ # ss1 = self.res1.get_fluxes()
110
+ # ss2 = self.res2.get_fluxes()
111
+ # diff = ss2 - ss1
112
+ # return pd.DataFrame(
113
+ # {"m1": ss1, "m2": ss2, "diff": diff, "rel_diff": diff / ss1}
114
+ # )
115
+
116
+ def plot_variables_relative_difference(self) -> plot.FigAxs:
117
+ """Plot the relative difference of time course variables."""
118
+ c1 = self.res1.variables
119
+ c2 = self.res2.variables
120
+
121
+ rel_diff = ((c2.loc[:, cast(list[str], c1.columns)] - c1) / c1).fillna(0)
122
+ fig, axs = plot.line_autogrouped(rel_diff, ylabel="")
123
+ plot.grid_labels(axs, ylabel="Relative difference")
124
+ fig.suptitle("Variables")
125
+ return fig, axs
126
+
127
+ def plot_fluxes_relative_difference(self) -> plot.FigAxs:
128
+ """Plot the relative difference of time course fluxes."""
129
+ v1 = self.res1.fluxes
130
+ v2 = self.res2.fluxes
131
+
132
+ rel_diff = ((v2.loc[:, cast(list[str], v1.columns)] - v1) / v1).fillna(0)
133
+ fig, axs = plot.line_autogrouped(rel_diff, ylabel="")
134
+ plot.grid_labels(axs, ylabel="Relative difference")
135
+ fig.suptitle("Fluxes")
136
+ return fig, axs
137
+
138
+
139
+ @dataclass
140
+ class ProtocolComparison:
141
+ """Compare two protocol time courses."""
142
+
143
+ res1: Result
144
+ res2: Result
145
+ protocol: pd.DataFrame
146
+
147
+ # @property
148
+ # def variables(self) -> pd.DataFrame:
149
+ # """Compare the steady state variables."""
150
+ # ss1 = self.res1.get_variables()
151
+ # ss2 = self.res2.get_variables()
152
+ # diff = ss2 - ss1
153
+ # return pd.DataFrame(
154
+ # {"m1": ss1, "m2": ss2, "diff": diff, "rel_diff": diff / ss1}
155
+ # )
156
+
157
+ # @property
158
+ # def fluxes(self) -> pd.DataFrame:
159
+ # """Compare the steady state fluxes."""
160
+ # ss1 = self.res1.get_fluxes()
161
+ # ss2 = self.res2.get_fluxes()
162
+ # diff = ss2 - ss1
163
+ # return pd.DataFrame(
164
+ # {"m1": ss1, "m2": ss2, "diff": diff, "rel_diff": diff / ss1}
165
+ # )
166
+
167
+ def plot_variables_relative_difference(
168
+ self,
169
+ shade_protocol_variable: str | None = None,
170
+ ) -> plot.FigAxs:
171
+ """Plot the relative difference of time course variables."""
172
+ c1 = self.res1.variables
173
+ c2 = self.res2.variables
174
+
175
+ rel_diff = ((c2.loc[:, cast(list[str], c1.columns)] - c1) / c1).fillna(0)
176
+ fig, axs = plot.line_autogrouped(rel_diff, ylabel="")
177
+ plot.grid_labels(axs, ylabel="Relative difference")
178
+ fig.suptitle("Variables")
179
+
180
+ if shade_protocol_variable is not None:
181
+ protocol = self.protocol[shade_protocol_variable]
182
+ for ax in axs:
183
+ plot.shade_protocol(protocol=protocol, ax=ax)
184
+ return fig, axs
185
+
186
+ def plot_fluxes_relative_difference(
187
+ self,
188
+ shade_protocol_variable: str | None = None,
189
+ ) -> plot.FigAxs:
190
+ """Plot the relative difference of time course fluxes."""
191
+ v1 = self.res1.fluxes
192
+ v2 = self.res2.fluxes
193
+
194
+ rel_diff = ((v2.loc[:, cast(list[str], v1.columns)] - v1) / v1).fillna(0)
195
+ fig, axs = plot.line_autogrouped(rel_diff, ylabel="")
196
+ plot.grid_labels(axs, ylabel="Relative difference")
197
+ fig.suptitle("Fluxes")
198
+
199
+ if shade_protocol_variable is not None:
200
+ protocol = self.protocol[shade_protocol_variable]
201
+ for ax in axs:
202
+ plot.shade_protocol(protocol=protocol, ax=ax)
203
+ return fig, axs
204
+
205
+
206
+ def steady_states(m1: Model, m2: Model) -> SteadyStateComparison:
207
+ """Compare the steady states of two models."""
208
+ return SteadyStateComparison(
209
+ res1=unwrap(Simulator(m1).simulate_to_steady_state().get_result()),
210
+ res2=unwrap(Simulator(m2).simulate_to_steady_state().get_result()),
211
+ )
212
+
213
+
214
+ def time_courses(m1: Model, m2: Model, time_points: ArrayLike) -> TimeCourseComparison:
215
+ """Compare the time courses of two models."""
216
+ return TimeCourseComparison(
217
+ res1=unwrap(
218
+ Simulator(m1).simulate_time_course(time_points=time_points).get_result()
219
+ ),
220
+ res2=unwrap(
221
+ Simulator(m2).simulate_time_course(time_points=time_points).get_result()
222
+ ),
223
+ )
224
+
225
+
226
+ def protocol_time_courses(
227
+ m1: Model,
228
+ m2: Model,
229
+ protocol: pd.DataFrame,
230
+ ) -> ProtocolComparison:
231
+ """Compare the time courses of two models."""
232
+ return ProtocolComparison(
233
+ res1=unwrap(
234
+ Simulator(m1).simulate_over_protocol(protocol=protocol).get_result()
235
+ ),
236
+ res2=unwrap(
237
+ Simulator(m2).simulate_over_protocol(protocol=protocol).get_result()
238
+ ),
239
+ protocol=protocol,
240
+ )
@@ -1,12 +1,24 @@
1
1
  """Diffing utilities for comparing models."""
2
2
 
3
- from collections.abc import Mapping
3
+ from __future__ import annotations
4
+
4
5
  from dataclasses import dataclass, field
6
+ from typing import TYPE_CHECKING
5
7
 
6
- from mxlpy.model import Model
7
8
  from mxlpy.types import Derived
8
9
 
9
- __all__ = ["DerivedDiff", "ModelDiff", "ReactionDiff", "model_diff", "soft_eq"]
10
+ if TYPE_CHECKING:
11
+ from collections.abc import Mapping
12
+
13
+ from mxlpy.model import Model
14
+
15
+ __all__ = [
16
+ "DerivedDiff",
17
+ "ModelDiff",
18
+ "ReactionDiff",
19
+ "model_diff",
20
+ "soft_eq",
21
+ ]
10
22
 
11
23
 
12
24
  @dataclass
@@ -181,7 +193,7 @@ def model_diff(m1: Model, m2: Model) -> ModelDiff:
181
193
  if (v2 := m2._variables.get(k)) is None: # noqa: SLF001
182
194
  diff.missing_variables.add(k)
183
195
  elif v1 != v2:
184
- diff.different_variables[k] = (v1, v2)
196
+ diff.different_variables[k] = (v1, v2) # type: ignore
185
197
 
186
198
  for k, v1 in m1._readouts.items(): # noqa: SLF001
187
199
  if (v2 := m2._readouts.get(k)) is None: # noqa: SLF001
mxlpy/fit.py CHANGED
@@ -18,13 +18,12 @@ from scipy.optimize import minimize
18
18
 
19
19
  from mxlpy.integrators import DefaultIntegrator
20
20
  from mxlpy.simulator import Simulator
21
- from mxlpy.types import (
22
- Array,
23
- ArrayLike,
24
- Callable,
25
- IntegratorType,
26
- cast,
27
- )
21
+ from mxlpy.types import Array, ArrayLike, Callable, IntegratorType, cast
22
+
23
+ if TYPE_CHECKING:
24
+ import pandas as pd
25
+
26
+ from mxlpy.model import Model
28
27
 
29
28
  __all__ = [
30
29
  "InitialGuess",
@@ -40,10 +39,6 @@ __all__ = [
40
39
  "time_course_over_protocol",
41
40
  ]
42
41
 
43
- if TYPE_CHECKING:
44
- import pandas as pd
45
-
46
- from mxlpy.model import Model
47
42
 
48
43
  type InitialGuess = dict[str, float]
49
44
  type ResidualFn = Callable[[Array], float]
mxlpy/fns.py CHANGED
@@ -2,11 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING
6
-
7
- if TYPE_CHECKING:
8
- from mxlpy.types import Float
9
-
10
5
  __all__ = [
11
6
  "add",
12
7
  "constant",
@@ -36,7 +31,7 @@ __all__ = [
36
31
  ###############################################################################
37
32
 
38
33
 
39
- def constant(x: Float) -> Float:
34
+ def constant(x: float) -> float:
40
35
  """Return a constant value regardless of other model components.
41
36
 
42
37
  Parameters
@@ -58,7 +53,7 @@ def constant(x: Float) -> Float:
58
53
  return x
59
54
 
60
55
 
61
- def neg(x: Float) -> Float:
56
+ def neg(x: float) -> float:
62
57
  """Calculate the negation of a value.
63
58
 
64
59
  Parameters
@@ -82,7 +77,7 @@ def neg(x: Float) -> Float:
82
77
  return -x
83
78
 
84
79
 
85
- def minus(x: Float, y: Float) -> Float:
80
+ def minus(x: float, y: float) -> float:
86
81
  """Calculate the difference between two values.
87
82
 
88
83
  Parameters
@@ -108,7 +103,7 @@ def minus(x: Float, y: Float) -> Float:
108
103
  return x - y
109
104
 
110
105
 
111
- def mul(x: Float, y: Float) -> Float:
106
+ def mul(x: float, y: float) -> float:
112
107
  """Calculate the product of two values.
113
108
 
114
109
  Parameters
@@ -134,7 +129,7 @@ def mul(x: Float, y: Float) -> Float:
134
129
  return x * y
135
130
 
136
131
 
137
- def div(x: Float, y: Float) -> Float:
132
+ def div(x: float, y: float) -> float:
138
133
  """Calculate the quotient of two values.
139
134
 
140
135
  Parameters
@@ -160,7 +155,7 @@ def div(x: Float, y: Float) -> Float:
160
155
  return x / y
161
156
 
162
157
 
163
- def one_div(x: Float) -> Float:
158
+ def one_div(x: float) -> float:
164
159
  """Calculate the reciprocal of a value.
165
160
 
166
161
  Parameters
@@ -184,7 +179,7 @@ def one_div(x: Float) -> Float:
184
179
  return 1.0 / x
185
180
 
186
181
 
187
- def neg_div(x: Float, y: Float) -> Float:
182
+ def neg_div(x: float, y: float) -> float:
188
183
  """Calculate the negative quotient of two values.
189
184
 
190
185
  Parameters
@@ -210,7 +205,7 @@ def neg_div(x: Float, y: Float) -> Float:
210
205
  return -x / y
211
206
 
212
207
 
213
- def twice(x: Float) -> Float:
208
+ def twice(x: float) -> float:
214
209
  """Calculate twice the value.
215
210
 
216
211
  Parameters
@@ -234,7 +229,7 @@ def twice(x: Float) -> Float:
234
229
  return x * 2
235
230
 
236
231
 
237
- def add(x: Float, y: Float) -> Float:
232
+ def add(x: float, y: float) -> float:
238
233
  """Calculate the sum of two values.
239
234
 
240
235
  Parameters
@@ -260,7 +255,7 @@ def add(x: Float, y: Float) -> Float:
260
255
  return x + y
261
256
 
262
257
 
263
- def proportional(x: Float, y: Float) -> Float:
258
+ def proportional(x: float, y: float) -> float:
264
259
  """Calculate the product of two values.
265
260
 
266
261
  Common in mass-action kinetics where x represents a rate constant
@@ -295,9 +290,9 @@ def proportional(x: Float, y: Float) -> Float:
295
290
 
296
291
 
297
292
  def moiety_1s(
298
- x: Float,
299
- x_total: Float,
300
- ) -> Float:
293
+ x: float,
294
+ x_total: float,
295
+ ) -> float:
301
296
  """Calculate conservation relationship for one substrate.
302
297
 
303
298
  Used for creating derived variables that represent moiety conservation,
@@ -328,10 +323,10 @@ def moiety_1s(
328
323
 
329
324
 
330
325
  def moiety_2s(
331
- x1: Float,
332
- x2: Float,
333
- x_total: Float,
334
- ) -> Float:
326
+ x1: float,
327
+ x2: float,
328
+ x_total: float,
329
+ ) -> float:
335
330
  """Calculate conservation relationship for two substrates.
336
331
 
337
332
  Used for creating derived variables that represent moiety conservation
@@ -369,7 +364,7 @@ def moiety_2s(
369
364
  ###############################################################################
370
365
 
371
366
 
372
- def mass_action_1s(s1: Float, k: Float) -> Float:
367
+ def mass_action_1s(s1: float, k: float) -> float:
373
368
  """Calculate irreversible mass action reaction rate with one substrate.
374
369
 
375
370
  Rate = k * [S]
@@ -398,7 +393,7 @@ def mass_action_1s(s1: Float, k: Float) -> Float:
398
393
  return k * s1
399
394
 
400
395
 
401
- def mass_action_1s_1p(s1: Float, p1: Float, kf: Float, kr: Float) -> Float:
396
+ def mass_action_1s_1p(s1: float, p1: float, kf: float, kr: float) -> float:
402
397
  """Calculate reversible mass action reaction rate with one substrate and one product.
403
398
 
404
399
  Rate = kf * [S] - kr * [P]
@@ -432,7 +427,7 @@ def mass_action_1s_1p(s1: Float, p1: Float, kf: Float, kr: Float) -> Float:
432
427
  return kf * s1 - kr * p1
433
428
 
434
429
 
435
- def mass_action_2s(s1: Float, s2: Float, k: Float) -> Float:
430
+ def mass_action_2s(s1: float, s2: float, k: float) -> float:
436
431
  """Calculate irreversible mass action reaction rate with two substrates.
437
432
 
438
433
  Rate = k * [S1] * [S2]
@@ -463,7 +458,7 @@ def mass_action_2s(s1: Float, s2: Float, k: Float) -> Float:
463
458
  return k * s1 * s2
464
459
 
465
460
 
466
- def mass_action_2s_1p(s1: Float, s2: Float, p1: Float, kf: Float, kr: Float) -> Float:
461
+ def mass_action_2s_1p(s1: float, s2: float, p1: float, kf: float, kr: float) -> float:
467
462
  """Calculate reversible mass action reaction rate with two substrates and one product.
468
463
 
469
464
  Rate = kf * [S1] * [S2] - kr * [P]
@@ -505,7 +500,7 @@ def mass_action_2s_1p(s1: Float, s2: Float, p1: Float, kf: Float, kr: Float) ->
505
500
  ###############################################################################
506
501
 
507
502
 
508
- def michaelis_menten_1s(s1: Float, vmax: Float, km1: Float) -> Float:
503
+ def michaelis_menten_1s(s1: float, vmax: float, km1: float) -> float:
509
504
  """Calculate irreversible Michaelis-Menten reaction rate for one substrate.
510
505
 
511
506
  Rate = Vmax * [S] / (Km + [S])
@@ -549,12 +544,12 @@ def michaelis_menten_1s(s1: Float, vmax: Float, km1: Float) -> Float:
549
544
 
550
545
 
551
546
  def michaelis_menten_2s(
552
- s1: Float,
553
- s2: Float,
554
- vmax: Float,
555
- km1: Float,
556
- km2: Float,
557
- ) -> Float:
547
+ s1: float,
548
+ s2: float,
549
+ vmax: float,
550
+ km1: float,
551
+ km2: float,
552
+ ) -> float:
558
553
  """Calculate Michaelis-Menten reaction rate (ping-pong) for two substrates.
559
554
 
560
555
  Rate = Vmax * [S1] * [S2] / ([S1]*[S2] + km1*[S2] + km2*[S1])
@@ -594,14 +589,14 @@ def michaelis_menten_2s(
594
589
 
595
590
 
596
591
  def michaelis_menten_3s(
597
- s1: Float,
598
- s2: Float,
599
- s3: Float,
600
- vmax: Float,
601
- km1: Float,
602
- km2: Float,
603
- km3: Float,
604
- ) -> Float:
592
+ s1: float,
593
+ s2: float,
594
+ s3: float,
595
+ vmax: float,
596
+ km1: float,
597
+ km2: float,
598
+ km3: float,
599
+ ) -> float:
605
600
  """Calculate Michaelis-Menten reaction rate (ping-pong) for three substrates.
606
601
 
607
602
  Rate = Vmax * [S1] * [S2] * [S3] / ([S1]*[S2] + km1*[S2]*[S3] + km2*[S1]*[S3] + km3*[S1]*[S2])
@@ -649,7 +644,7 @@ def michaelis_menten_3s(
649
644
  ###############################################################################
650
645
 
651
646
 
652
- def diffusion_1s_1p(inside: Float, outside: Float, k: Float) -> Float:
647
+ def diffusion_1s_1p(inside: float, outside: float, k: float) -> float:
653
648
  """Calculate diffusion rate between two compartments.
654
649
 
655
650
  Rate = k * ([outside] - [inside])
mxlpy/identify.py CHANGED
@@ -1,6 +1,9 @@
1
1
  """Numerical parameter identification estimations."""
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  from functools import partial
6
+ from typing import TYPE_CHECKING
4
7
 
5
8
  import numpy as np
6
9
  import pandas as pd
@@ -8,11 +11,15 @@ from tqdm import tqdm
8
11
 
9
12
  from mxlpy import fit
10
13
  from mxlpy.distributions import LogNormal, sample
11
- from mxlpy.model import Model
12
14
  from mxlpy.parallel import parallelise
13
- from mxlpy.types import Array
14
15
 
15
- __all__ = ["profile_likelihood"]
16
+ if TYPE_CHECKING:
17
+ from mxlpy.model import Model
18
+ from mxlpy.types import Array
19
+
20
+ __all__ = [
21
+ "profile_likelihood",
22
+ ]
16
23
 
17
24
 
18
25
  def _mc_fit_time_course_worker(
@@ -6,9 +6,6 @@ It includes support for both Assimulo and Scipy integrators, with Assimulo being
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- __all__ = ["DefaultIntegrator"]
10
-
11
-
12
9
  from .int_scipy import Scipy
13
10
 
14
11
  try:
@@ -17,3 +14,7 @@ try:
17
14
  DefaultIntegrator = Assimulo
18
15
  except ImportError:
19
16
  DefaultIntegrator = Scipy
17
+
18
+ __all__ = [
19
+ "DefaultIntegrator",
20
+ ]
@@ -2,14 +2,9 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from dataclasses import dataclass
6
-
7
- __all__ = [
8
- "Assimulo",
9
- ]
10
-
11
5
  import contextlib
12
6
  import os
7
+ from dataclasses import dataclass
13
8
  from typing import TYPE_CHECKING, Literal
14
9
 
15
10
  import numpy as np
@@ -25,6 +20,11 @@ if TYPE_CHECKING:
25
20
  from mxlpy.types import Array, ArrayLike
26
21
 
27
22
 
23
+ __all__ = [
24
+ "Assimulo",
25
+ ]
26
+
27
+
28
28
  @dataclass
29
29
  class Assimulo:
30
30
  """Assimulo integrator for solving ODEs.
@@ -97,7 +97,11 @@ class Assimulo:
97
97
  if steps is None:
98
98
  steps = 0
99
99
  try:
100
- return self.integrator.simulate(t_end, steps) # type: ignore
100
+ t, y = self.integrator.simulate(t_end, steps)
101
+ return (
102
+ np.atleast_1d(np.array(t, dtype=float)),
103
+ np.atleast_2d(np.array(y, dtype=float)),
104
+ )
101
105
  except CVodeError:
102
106
  return None, None
103
107
 
@@ -116,8 +120,11 @@ class Assimulo:
116
120
 
117
121
  """
118
122
  try:
119
- t, y = self.integrator.simulate(time_points[-1], 0, time_points) # type: ignore
120
- return np.array(t, dtype=float), np.array(y, dtype=float)
123
+ t, y = self.integrator.simulate(time_points[-1], 0, time_points)
124
+ return (
125
+ np.atleast_1d(np.array(t, dtype=float)),
126
+ np.atleast_2d(np.array(y, dtype=float)),
127
+ )
121
128
  except CVodeError:
122
129
  return None, None
123
130