mxlpy 0.21.0__py3-none-any.whl → 0.23.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 +15 -2
- mxlpy/carousel.py +6 -4
- mxlpy/compare.py +4 -8
- mxlpy/experimental/diff.py +1 -1
- mxlpy/fit.py +195 -99
- mxlpy/identify.py +14 -9
- 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 +15 -6
- mxlpy/label_map.py +6 -7
- mxlpy/linear_label_map.py +3 -1
- mxlpy/mc.py +25 -22
- mxlpy/mca.py +10 -6
- mxlpy/meta/__init__.py +5 -3
- mxlpy/meta/codegen_latex.py +44 -30
- mxlpy/meta/codegen_model.py +175 -0
- mxlpy/meta/codegen_mxlpy.py +254 -0
- mxlpy/meta/source_tools.py +506 -221
- mxlpy/meta/sympy_tools.py +117 -0
- mxlpy/model.py +758 -257
- mxlpy/plot.py +16 -14
- mxlpy/report.py +153 -90
- mxlpy/sbml/_export.py +22 -11
- mxlpy/sbml/_import.py +68 -547
- mxlpy/scan.py +39 -243
- mxlpy/simulator.py +109 -283
- mxlpy/symbolic/symbolic_model.py +29 -17
- mxlpy/types.py +694 -97
- mxlpy/units.py +133 -0
- {mxlpy-0.21.0.dist-info → mxlpy-0.23.0.dist-info}/METADATA +4 -1
- mxlpy-0.23.0.dist-info/RECORD +57 -0
- mxlpy/meta/codegen_modebase.py +0 -112
- mxlpy/meta/codegen_py.py +0 -115
- mxlpy/sbml/_mathml.py +0 -692
- mxlpy/sbml/_unit_conversion.py +0 -74
- mxlpy-0.21.0.dist-info/RECORD +0 -56
- {mxlpy-0.21.0.dist-info → mxlpy-0.23.0.dist-info}/WHEEL +0 -0
- {mxlpy-0.21.0.dist-info → mxlpy-0.23.0.dist-info}/licenses/LICENSE +0 -0
mxlpy/plot.py
CHANGED
@@ -28,6 +28,7 @@ import numpy as np
|
|
28
28
|
import pandas as pd
|
29
29
|
import seaborn as sns
|
30
30
|
from cycler import cycler
|
31
|
+
from matplotlib import colormaps
|
31
32
|
from matplotlib import pyplot as plt
|
32
33
|
from matplotlib.axes import Axes
|
33
34
|
from matplotlib.colors import (
|
@@ -37,6 +38,8 @@ from matplotlib.colors import (
|
|
37
38
|
colorConverter, # type: ignore
|
38
39
|
)
|
39
40
|
from matplotlib.figure import Figure
|
41
|
+
from matplotlib.legend import Legend
|
42
|
+
from matplotlib.patches import Patch
|
40
43
|
from mpl_toolkits.mplot3d import Axes3D
|
41
44
|
|
42
45
|
from mxlpy.label_map import LabelMapper
|
@@ -541,7 +544,7 @@ def bars(
|
|
541
544
|
sns.barplot(data=cast(pd.DataFrame, x), ax=ax)
|
542
545
|
|
543
546
|
if xlabel is None:
|
544
|
-
xlabel = x.index.name if x.index.name is not None else ""
|
547
|
+
xlabel = x.index.name if x.index.name is not None else "" # type: ignore
|
545
548
|
_default_labels(ax, xlabel=xlabel, ylabel=ylabel)
|
546
549
|
if isinstance(x, pd.DataFrame):
|
547
550
|
ax.legend(x.columns)
|
@@ -651,7 +654,7 @@ def lines(
|
|
651
654
|
)
|
652
655
|
_default_labels(
|
653
656
|
ax,
|
654
|
-
xlabel=x.index.name if xlabel is None else xlabel,
|
657
|
+
xlabel=x.index.name if xlabel is None else xlabel, # type: ignore
|
655
658
|
ylabel=ylabel,
|
656
659
|
)
|
657
660
|
if legend:
|
@@ -792,7 +795,11 @@ def line_mean_std(
|
|
792
795
|
color=color,
|
793
796
|
alpha=alpha,
|
794
797
|
)
|
795
|
-
_default_labels(
|
798
|
+
_default_labels(
|
799
|
+
ax,
|
800
|
+
xlabel=df.index.name, # type: ignore
|
801
|
+
ylabel=None,
|
802
|
+
)
|
796
803
|
return fig, ax
|
797
804
|
|
798
805
|
|
@@ -865,11 +872,11 @@ def _create_heatmap(
|
|
865
872
|
if title is not None:
|
866
873
|
ax.set_title(title)
|
867
874
|
ax.set_xticks(
|
868
|
-
np.arange(0, len(df.columns), 1, dtype=float) + 0.5,
|
875
|
+
np.arange(0, len(df.columns), 1, dtype=float) + 0.5, # type: ignore
|
869
876
|
labels=xticklabels,
|
870
877
|
)
|
871
878
|
ax.set_yticks(
|
872
|
-
np.arange(0, len(df.index), 1, dtype=float) + 0.5,
|
879
|
+
np.arange(0, len(df.index), 1, dtype=float) + 0.5, # type: ignore
|
873
880
|
labels=yticklabels,
|
874
881
|
)
|
875
882
|
|
@@ -906,8 +913,8 @@ def heatmap(
|
|
906
913
|
ax=ax,
|
907
914
|
df=df,
|
908
915
|
title=title,
|
909
|
-
xlabel=df.index.name,
|
910
|
-
ylabel=df.columns.name,
|
916
|
+
xlabel=df.index.name, # type: ignore
|
917
|
+
ylabel=df.columns.name, # type: ignore
|
911
918
|
xticklabels=cast(list, df.columns),
|
912
919
|
yticklabels=cast(list, df.index),
|
913
920
|
annotate=annotate,
|
@@ -943,8 +950,8 @@ def heatmap_from_2d_idx(
|
|
943
950
|
|
944
951
|
return _create_heatmap(
|
945
952
|
df=df2d,
|
946
|
-
xlabel=df2d.index.name,
|
947
|
-
ylabel=df2d.columns.name,
|
953
|
+
xlabel=df2d.index.name, # type: ignore
|
954
|
+
ylabel=df2d.columns.name, # type: ignore
|
948
955
|
xticklabels=[f"{i:.2f}" for i in df2d.columns],
|
949
956
|
yticklabels=[f"{i:.2f}" for i in df2d.index],
|
950
957
|
ax=ax,
|
@@ -1064,11 +1071,6 @@ def shade_protocol(
|
|
1064
1071
|
add_legend: bool = True,
|
1065
1072
|
) -> None:
|
1066
1073
|
"""Shade the given protocol on the given axis."""
|
1067
|
-
from matplotlib import colormaps
|
1068
|
-
from matplotlib.colors import Normalize
|
1069
|
-
from matplotlib.legend import Legend
|
1070
|
-
from matplotlib.patches import Patch
|
1071
|
-
|
1072
1074
|
cmap = colormaps[cmap_name]
|
1073
1075
|
norm = Normalize(
|
1074
1076
|
vmin=protocol.min() if vmin is None else vmin,
|
mxlpy/report.py
CHANGED
@@ -3,25 +3,25 @@
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
5
|
from collections.abc import Callable
|
6
|
+
from dataclasses import dataclass
|
6
7
|
from datetime import UTC, datetime
|
7
8
|
from pathlib import Path
|
8
9
|
from typing import cast
|
9
10
|
|
10
11
|
import sympy
|
11
12
|
|
12
|
-
from mxlpy.meta.
|
13
|
+
from mxlpy.meta.sympy_tools import fn_to_sympy, list_of_symbols
|
13
14
|
from mxlpy.model import Model
|
14
15
|
|
15
|
-
__all__ = [
|
16
|
-
"AnalysisFn",
|
17
|
-
"markdown",
|
18
|
-
]
|
16
|
+
__all__ = ["AnalysisFn", "MarkdownReport", "markdown"]
|
19
17
|
|
20
18
|
type AnalysisFn = Callable[[Model, Model, Path], tuple[str, Path]]
|
21
19
|
|
22
20
|
|
23
|
-
def
|
24
|
-
|
21
|
+
def _latex_view(expr: sympy.Expr | None) -> str:
|
22
|
+
if expr is None:
|
23
|
+
return "<span style='color:red'>PARSE ERROR<span>"
|
24
|
+
return f"${sympy.latex(expr)}$"
|
25
25
|
|
26
26
|
|
27
27
|
def _new_removed_changed[T](
|
@@ -44,48 +44,71 @@ def _table_header(items: list[str]) -> str:
|
|
44
44
|
return f"{_table_row(items)}\n{_table_row(['---'] * len(items))}"
|
45
45
|
|
46
46
|
|
47
|
+
@dataclass
|
48
|
+
class MarkdownReport:
|
49
|
+
"""Report of model comparison."""
|
50
|
+
|
51
|
+
data: str
|
52
|
+
|
53
|
+
def __str__(self) -> str:
|
54
|
+
"""Markdown string representation."""
|
55
|
+
return self.data
|
56
|
+
|
57
|
+
def __repr__(self) -> str:
|
58
|
+
"""Markdown string representation."""
|
59
|
+
return self.data
|
60
|
+
|
61
|
+
def _repr_markdown_(self) -> str:
|
62
|
+
return self.data
|
63
|
+
|
64
|
+
def write(self, path: Path) -> None:
|
65
|
+
"""Write report to file."""
|
66
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
67
|
+
|
68
|
+
with path.open("w+") as fp:
|
69
|
+
fp.write(self.data)
|
70
|
+
|
71
|
+
|
47
72
|
def markdown(
|
48
73
|
m1: Model,
|
49
74
|
m2: Model,
|
75
|
+
*,
|
50
76
|
analyses: list[AnalysisFn] | None = None,
|
51
77
|
rel_change: float = 1e-2,
|
52
78
|
img_path: Path = Path(),
|
53
|
-
|
79
|
+
m1_name: str = "model 1",
|
80
|
+
m2_name: str = "model 2",
|
81
|
+
include_rhs: bool = True,
|
82
|
+
) -> MarkdownReport:
|
54
83
|
"""Generate a markdown report comparing two models.
|
55
84
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
The
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
>>> # With custom analysis function
|
84
|
-
>>> def custom_analysis(m1, m2, path):
|
85
|
-
... return "## Custom analysis", path / "image.png"
|
86
|
-
>>> report = markdown(m1, m2, analyses=[custom_analysis])
|
87
|
-
>>> "Custom analysis" in report
|
88
|
-
True
|
85
|
+
Args:
|
86
|
+
m1: The first model to compare
|
87
|
+
m2: The second model to compare
|
88
|
+
analyses: A list of functions that analyze both models and return a report section with image
|
89
|
+
rel_change: The relative change threshold for numerical differences
|
90
|
+
img_path: The path to save images
|
91
|
+
m1_name: Name of the first model
|
92
|
+
m2_name: Name of the second model
|
93
|
+
include_rhs: Whether to include numerical differences in the right hand side
|
94
|
+
|
95
|
+
Returns:
|
96
|
+
str: Markdown formatted report comparing the two models
|
97
|
+
|
98
|
+
Examples:
|
99
|
+
>>> from mxlpy import Model
|
100
|
+
>>> m1 = Model().add_parameter("k1", 0.1).add_variable("S", 1.0)
|
101
|
+
>>> m2 = Model().add_parameter("k1", 0.2).add_variable("S", 1.0)
|
102
|
+
>>> report = markdown(m1, m2)
|
103
|
+
>>> "Parameters" in report and "k1" in report
|
104
|
+
True
|
105
|
+
|
106
|
+
>>> # With custom analysis function
|
107
|
+
>>> def custom_analysis(m1, m2, path):
|
108
|
+
... return "## Custom analysis", path / "image.png"
|
109
|
+
>>> report = markdown(m1, m2, analyses=[custom_analysis])
|
110
|
+
>>> "Custom analysis" in report
|
111
|
+
True
|
89
112
|
|
90
113
|
"""
|
91
114
|
content: list[str] = [
|
@@ -101,20 +124,20 @@ def markdown(
|
|
101
124
|
# Model stats
|
102
125
|
content.extend(
|
103
126
|
[
|
104
|
-
"| Model component |
|
127
|
+
f"| Model component | {m1_name} | {m2_name} |",
|
105
128
|
"| --- | --- | --- |",
|
106
|
-
f"| variables | {len(m1.
|
107
|
-
f"| parameters | {len(m1.
|
108
|
-
f"| derived parameters | {len(m1.
|
109
|
-
f"| derived variables | {len(m1.
|
110
|
-
f"| reactions | {len(m1.
|
129
|
+
f"| variables | {len(m1.get_raw_parameters())} | {len(m2.get_raw_parameters())}|",
|
130
|
+
f"| parameters | {len(m1.get_parameter_values())} | {len(m2.get_parameter_values())}|",
|
131
|
+
f"| derived parameters | {len(m1.get_derived_parameters())} | {len(m2.get_derived_parameters())}|",
|
132
|
+
f"| derived variables | {len(m1.get_derived_variables())} | {len(m2.get_derived_variables())}|",
|
133
|
+
f"| reactions | {len(m1.get_raw_reactions())} | {len(m2.get_raw_reactions())}|",
|
111
134
|
f"| surrogates | {len(m1._surrogates)} | {len(m2._surrogates)}|", # noqa: SLF001
|
112
135
|
]
|
113
136
|
)
|
114
137
|
|
115
138
|
# Variables
|
116
139
|
new_variables, removed_variables, changed_variables = _new_removed_changed(
|
117
|
-
m1.
|
140
|
+
m1.get_initial_conditions(), m2.get_initial_conditions()
|
118
141
|
)
|
119
142
|
variables = []
|
120
143
|
variables.extend(
|
@@ -131,8 +154,8 @@ def markdown(
|
|
131
154
|
if len(variables) >= 1:
|
132
155
|
content.extend(
|
133
156
|
(
|
134
|
-
"## Variables\n
|
135
|
-
"| Name |
|
157
|
+
"\n## Variables\n",
|
158
|
+
f"| Name | {m1_name} | {m2_name} |",
|
136
159
|
"| ---- | --------- | --------- |",
|
137
160
|
)
|
138
161
|
)
|
@@ -140,7 +163,7 @@ def markdown(
|
|
140
163
|
|
141
164
|
# Parameters
|
142
165
|
new_parameters, removed_parameters, changed_parameters = _new_removed_changed(
|
143
|
-
m1.
|
166
|
+
m1.get_parameter_values(), m2.get_parameter_values()
|
144
167
|
)
|
145
168
|
pars = []
|
146
169
|
pars.extend(
|
@@ -157,8 +180,8 @@ def markdown(
|
|
157
180
|
if len(pars) >= 1:
|
158
181
|
content.extend(
|
159
182
|
(
|
160
|
-
"## Parameters\n
|
161
|
-
"| Name |
|
183
|
+
"\n## Parameters\n",
|
184
|
+
f"| Name | {m1_name} | {m2_name} |",
|
162
185
|
"| ---- | --------- | --------- |",
|
163
186
|
)
|
164
187
|
)
|
@@ -166,17 +189,37 @@ def markdown(
|
|
166
189
|
|
167
190
|
# Derived
|
168
191
|
new_derived, removed_derived, changed_derived = _new_removed_changed(
|
169
|
-
m1.
|
192
|
+
m1.get_raw_derived(),
|
193
|
+
m2.get_raw_derived(),
|
170
194
|
)
|
171
195
|
derived = []
|
172
196
|
for k, v in new_derived.items():
|
173
|
-
expr =
|
174
|
-
|
197
|
+
expr = _latex_view(
|
198
|
+
fn_to_sympy(
|
199
|
+
v.fn,
|
200
|
+
origin=k,
|
201
|
+
model_args=list_of_symbols(v.args),
|
202
|
+
)
|
203
|
+
)
|
204
|
+
derived.append(f"| <span style='color:green'>{k}<span> | - | {expr} |")
|
205
|
+
|
175
206
|
for k, (v1, v2) in changed_derived.items():
|
176
|
-
expr1 =
|
177
|
-
|
207
|
+
expr1 = _latex_view(
|
208
|
+
fn_to_sympy(
|
209
|
+
v1.fn,
|
210
|
+
origin=k,
|
211
|
+
model_args=list_of_symbols(v1.args),
|
212
|
+
)
|
213
|
+
)
|
214
|
+
expr2 = _latex_view(
|
215
|
+
fn_to_sympy(
|
216
|
+
v2.fn,
|
217
|
+
origin=k,
|
218
|
+
model_args=list_of_symbols(v2.args),
|
219
|
+
)
|
220
|
+
)
|
178
221
|
derived.append(
|
179
|
-
f"| <span style='color: orange'>{k}</span> |
|
222
|
+
f"| <span style='color: orange'>{k}</span> | {expr1} | {expr2} |"
|
180
223
|
)
|
181
224
|
derived.extend(
|
182
225
|
f"| <span style='color:red'>{k}</span> | - | - |" for k in removed_derived
|
@@ -184,8 +227,8 @@ def markdown(
|
|
184
227
|
if len(derived) >= 1:
|
185
228
|
content.extend(
|
186
229
|
(
|
187
|
-
"## Derived\n
|
188
|
-
"| Name |
|
230
|
+
"\n## Derived\n",
|
231
|
+
f"| Name | {m1_name} | {m2_name} |",
|
189
232
|
"| ---- | --------- | --------- |",
|
190
233
|
)
|
191
234
|
)
|
@@ -193,17 +236,36 @@ def markdown(
|
|
193
236
|
|
194
237
|
# Reactions
|
195
238
|
new_reactions, removed_reactions, changed_reactions = _new_removed_changed(
|
196
|
-
m1.
|
239
|
+
m1.get_raw_reactions(), m2.get_raw_reactions()
|
197
240
|
)
|
198
241
|
reactions = []
|
199
242
|
for k, v in new_reactions.items():
|
200
|
-
expr =
|
201
|
-
|
243
|
+
expr = _latex_view(
|
244
|
+
fn_to_sympy(
|
245
|
+
v.fn,
|
246
|
+
origin=k,
|
247
|
+
model_args=list_of_symbols(v.args),
|
248
|
+
)
|
249
|
+
)
|
250
|
+
reactions.append(f"| <span style='color:green'>{k}<span> | - | {expr} |")
|
251
|
+
|
202
252
|
for k, (v1, v2) in changed_reactions.items():
|
203
|
-
expr1 =
|
204
|
-
|
253
|
+
expr1 = _latex_view(
|
254
|
+
fn_to_sympy(
|
255
|
+
v1.fn,
|
256
|
+
origin=k,
|
257
|
+
model_args=list_of_symbols(v1.args),
|
258
|
+
)
|
259
|
+
)
|
260
|
+
expr2 = _latex_view(
|
261
|
+
fn_to_sympy(
|
262
|
+
v2.fn,
|
263
|
+
origin=k,
|
264
|
+
model_args=list_of_symbols(v2.args),
|
265
|
+
)
|
266
|
+
)
|
205
267
|
reactions.append(
|
206
|
-
f"| <span style='color: orange'>{k}</span> |
|
268
|
+
f"| <span style='color: orange'>{k}</span> | {expr1} | {expr2} |"
|
207
269
|
)
|
208
270
|
reactions.extend(
|
209
271
|
f"| <span style='color:red'>{k}</span> | - | - |" for k in removed_reactions
|
@@ -212,8 +274,8 @@ def markdown(
|
|
212
274
|
if len(reactions) >= 1:
|
213
275
|
content.extend(
|
214
276
|
(
|
215
|
-
"## Reactions\n
|
216
|
-
"| Name |
|
277
|
+
"\n## Reactions\n",
|
278
|
+
f"| Name | {m1_name} | {m2_name} |",
|
217
279
|
"| ---- | --------- | --------- |",
|
218
280
|
)
|
219
281
|
)
|
@@ -221,8 +283,8 @@ def markdown(
|
|
221
283
|
|
222
284
|
# Now check for any numerical differences
|
223
285
|
dependent = []
|
224
|
-
d1 = m1.
|
225
|
-
d2 = m2.
|
286
|
+
d1 = m1.get_args()
|
287
|
+
d2 = m2.get_args()
|
226
288
|
rel_diff = ((d1 - d2) / d1).dropna()
|
227
289
|
for k, v in rel_diff.loc[rel_diff.abs() >= rel_change].items():
|
228
290
|
k = cast(str, k)
|
@@ -233,30 +295,31 @@ def markdown(
|
|
233
295
|
content.extend(
|
234
296
|
(
|
235
297
|
"## Numerical differences of dependent values\n\n",
|
236
|
-
"| Name |
|
298
|
+
f"| Name | {m1_name} | {m2_name} | Relative Change | ",
|
237
299
|
"| ---- | --------- | --------- | --------------- | ",
|
238
300
|
)
|
239
301
|
)
|
240
302
|
content.append("\n".join(dependent))
|
241
303
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
k
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
if len(rhs) >= 1:
|
252
|
-
content.extend(
|
253
|
-
(
|
254
|
-
"## Numerical differences of right hand side values\n\n",
|
255
|
-
"| Name | Old Value | New Value | Relative Change | ",
|
256
|
-
"| ---- | --------- | --------- | --------------- | ",
|
304
|
+
if include_rhs:
|
305
|
+
rhs = []
|
306
|
+
r1 = m1.get_right_hand_side()
|
307
|
+
r2 = m2.get_right_hand_side()
|
308
|
+
rel_diff = ((r1 - r2) / r1).dropna()
|
309
|
+
for k, v in rel_diff.loc[rel_diff.abs() >= rel_change].items():
|
310
|
+
k = cast(str, k)
|
311
|
+
rhs.append(
|
312
|
+
f"| <span style='color:orange'>{k}</span> | {r1[k]:.2f} | {r2[k]:.2f} | {v:.1%} |"
|
257
313
|
)
|
258
|
-
)
|
259
|
-
|
314
|
+
if len(rhs) >= 1:
|
315
|
+
content.extend(
|
316
|
+
(
|
317
|
+
"\n## Numerical differences of right hand side values\n",
|
318
|
+
f"| Name | {m1_name} | {m2_name} | Relative Change | ",
|
319
|
+
"| ---- | --------- | --------- | --------------- | ",
|
320
|
+
)
|
321
|
+
)
|
322
|
+
content.append("\n".join(rhs))
|
260
323
|
|
261
324
|
# Comparison functions
|
262
325
|
if analyses is not None:
|
@@ -266,4 +329,4 @@ def markdown(
|
|
266
329
|
# content.append(f"")
|
267
330
|
content.append(f"<img src='{img_path}' alt='{name}' width='500'/>")
|
268
331
|
|
269
|
-
return "\n".join(content)
|
332
|
+
return MarkdownReport(data="\n".join(content))
|
mxlpy/sbml/_export.py
CHANGED
@@ -10,7 +10,7 @@ import numpy as np
|
|
10
10
|
|
11
11
|
from mxlpy.meta.source_tools import get_fn_ast
|
12
12
|
from mxlpy.sbml._data import AtomicUnit, Compartment
|
13
|
-
from mxlpy.types import Derived
|
13
|
+
from mxlpy.types import Derived, InitialAssignment
|
14
14
|
|
15
15
|
if TYPE_CHECKING:
|
16
16
|
from collections.abc import Callable
|
@@ -440,30 +440,32 @@ def _create_sbml_variables(
|
|
440
440
|
sbml_model : libsbml.Model
|
441
441
|
|
442
442
|
"""
|
443
|
-
for name,
|
443
|
+
for name, variable in model.get_raw_variables().items():
|
444
444
|
cpd = sbml_model.createSpecies()
|
445
445
|
cpd.setId(_convert_id_to_sbml(id_=name, prefix="CPD"))
|
446
446
|
|
447
447
|
cpd.setConstant(False)
|
448
448
|
cpd.setBoundaryCondition(False)
|
449
449
|
cpd.setHasOnlySubstanceUnits(False)
|
450
|
-
|
450
|
+
# cpd.setUnit() # FIXME: implement
|
451
|
+
if isinstance((init := variable.initial_value), InitialAssignment):
|
451
452
|
ar = sbml_model.createInitialAssignment()
|
452
453
|
ar.setId(_convert_id_to_sbml(id_=name, prefix="IA"))
|
453
454
|
ar.setName(_convert_id_to_sbml(id_=name, prefix="IA"))
|
454
455
|
ar.setVariable(_convert_id_to_sbml(id_=name, prefix="IA"))
|
455
|
-
ar.setMath(_sbmlify_fn(
|
456
|
+
ar.setMath(_sbmlify_fn(init.fn, init.args))
|
456
457
|
else:
|
457
|
-
cpd.setInitialAmount(float(
|
458
|
+
cpd.setInitialAmount(float(init))
|
458
459
|
|
459
460
|
|
460
461
|
def _create_sbml_derived_variables(*, model: Model, sbml_model: libsbml.Model) -> None:
|
461
|
-
for name, dv in model.
|
462
|
+
for name, dv in model.get_derived_variables().items():
|
462
463
|
sbml_ar = sbml_model.createAssignmentRule()
|
463
464
|
sbml_ar.setId(_convert_id_to_sbml(id_=name, prefix="AR"))
|
464
465
|
sbml_ar.setName(_convert_id_to_sbml(id_=name, prefix="AR"))
|
465
466
|
sbml_ar.setVariable(_convert_id_to_sbml(id_=name, prefix="AR"))
|
466
467
|
sbml_ar.setMath(_sbmlify_fn(dv.fn, dv.args))
|
468
|
+
# cpd.setUnit() # FIXME: implement
|
467
469
|
|
468
470
|
|
469
471
|
def _create_derived_parameter(
|
@@ -477,6 +479,7 @@ def _create_derived_parameter(
|
|
477
479
|
ar.setName(_convert_id_to_sbml(id_=name, prefix="AR"))
|
478
480
|
ar.setVariable(_convert_id_to_sbml(id_=name, prefix="AR"))
|
479
481
|
ar.setMath(_sbmlify_fn(dp.fn, dp.args))
|
482
|
+
# cpd.setUnit() # FIXME: implement
|
480
483
|
|
481
484
|
|
482
485
|
def _create_sbml_parameters(
|
@@ -491,15 +494,23 @@ def _create_sbml_parameters(
|
|
491
494
|
sbml_model : libsbml.Model
|
492
495
|
|
493
496
|
"""
|
494
|
-
for
|
497
|
+
for name, value in model.get_raw_parameters().items():
|
495
498
|
k = sbml_model.createParameter()
|
496
|
-
k.setId(_convert_id_to_sbml(id_=
|
499
|
+
k.setId(_convert_id_to_sbml(id_=name, prefix="PAR"))
|
497
500
|
k.setConstant(True)
|
498
|
-
|
501
|
+
|
502
|
+
if isinstance((init := value.value), InitialAssignment):
|
503
|
+
ar = sbml_model.createInitialAssignment()
|
504
|
+
ar.setId(_convert_id_to_sbml(id_=name, prefix="IA"))
|
505
|
+
ar.setName(_convert_id_to_sbml(id_=name, prefix="IA"))
|
506
|
+
ar.setVariable(_convert_id_to_sbml(id_=name, prefix="IA"))
|
507
|
+
ar.setMath(_sbmlify_fn(init.fn, init.args))
|
508
|
+
else:
|
509
|
+
k.setValue(float(init))
|
499
510
|
|
500
511
|
|
501
512
|
def _create_sbml_derived_parameters(*, model: Model, sbml_model: libsbml.Model) -> None:
|
502
|
-
for name, dp in model.
|
513
|
+
for name, dp in model.get_derived_parameters().items():
|
503
514
|
_create_derived_parameter(sbml_model, name, dp)
|
504
515
|
|
505
516
|
|
@@ -509,7 +520,7 @@ def _create_sbml_reactions(
|
|
509
520
|
sbml_model: libsbml.Model,
|
510
521
|
) -> None:
|
511
522
|
"""Create the reactions for the sbml model."""
|
512
|
-
for name, rxn in model.
|
523
|
+
for name, rxn in model.get_raw_reactions().items():
|
513
524
|
sbml_rxn = sbml_model.createReaction()
|
514
525
|
sbml_rxn.setId(_convert_id_to_sbml(id_=name, prefix="RXN"))
|
515
526
|
sbml_rxn.setName(name)
|