modelbase2 0.4.0__py3-none-any.whl → 0.5.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.
- modelbase2/experimental/codegen.py +1 -1
- modelbase2/experimental/tex.py +4 -8
- modelbase2/model.py +56 -8
- modelbase2/plot.py +2 -2
- modelbase2/sbml/_import.py +5 -1
- {modelbase2-0.4.0.dist-info → modelbase2-0.5.0.dist-info}/METADATA +1 -1
- {modelbase2-0.4.0.dist-info → modelbase2-0.5.0.dist-info}/RECORD +9 -9
- {modelbase2-0.4.0.dist-info → modelbase2-0.5.0.dist-info}/WHEEL +0 -0
- {modelbase2-0.4.0.dist-info → modelbase2-0.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -211,7 +211,7 @@ def generate_model_code_py(model: Model) -> str:
|
|
211
211
|
stoich_source = []
|
212
212
|
for variable, stoich in stoichiometries.items():
|
213
213
|
stoich_source.append(
|
214
|
-
f" d{variable}dt = {conditional_join(stoich, lambda x: x.startswith(
|
214
|
+
f" d{variable}dt = {conditional_join(stoich, lambda x: x.startswith('-'), ' ', ' + ')}"
|
215
215
|
)
|
216
216
|
|
217
217
|
# Surrogates
|
modelbase2/experimental/tex.py
CHANGED
@@ -508,14 +508,10 @@ def get_model_tex_diff(
|
|
508
508
|
gls = default_init(gls)
|
509
509
|
section_label = "sec:model-diff"
|
510
510
|
|
511
|
-
return f"""{
|
511
|
+
return f"""{" start autogenerated ":%^60}
|
512
512
|
{_clearpage()}
|
513
|
-
{_subsubsection(
|
514
|
-
{(
|
515
|
-
(_to_tex_export(m1) - _to_tex_export(m2))
|
516
|
-
.rename_with_glossary(gls)
|
517
|
-
.export_all()
|
518
|
-
)}
|
513
|
+
{_subsubsection("Model changes")}{_label(section_label)}
|
514
|
+
{((_to_tex_export(m1) - _to_tex_export(m2)).rename_with_glossary(gls).export_all())}
|
519
515
|
{_clearpage()}
|
520
|
-
{
|
516
|
+
{" end autogenerated ":%^60}
|
521
517
|
"""
|
modelbase2/model.py
CHANGED
@@ -25,7 +25,13 @@ from modelbase2.types import (
|
|
25
25
|
Readout,
|
26
26
|
)
|
27
27
|
|
28
|
-
__all__ = [
|
28
|
+
__all__ = [
|
29
|
+
"ArityMismatchError",
|
30
|
+
"CircularDependencyError",
|
31
|
+
"MissingDependenciesError",
|
32
|
+
"Model",
|
33
|
+
"ModelCache",
|
34
|
+
]
|
29
35
|
|
30
36
|
if TYPE_CHECKING:
|
31
37
|
from collections.abc import Iterable, Mapping
|
@@ -34,19 +40,38 @@ if TYPE_CHECKING:
|
|
34
40
|
from modelbase2.types import AbstractSurrogate, Callable, Param, RateFn, RetType
|
35
41
|
|
36
42
|
|
37
|
-
class
|
43
|
+
class MissingDependenciesError(Exception):
|
38
44
|
"""Raised when dependencies cannot be sorted topologically.
|
39
45
|
|
40
46
|
This typically indicates circular dependencies in model components.
|
41
47
|
"""
|
42
48
|
|
43
|
-
def __init__(self,
|
49
|
+
def __init__(self, not_solvable: dict[str, list[str]]) -> None:
|
44
50
|
"""Initialise exception."""
|
51
|
+
missing_by_module = "\n".join(f"\t{k}: {v}" for k, v in not_solvable.items())
|
45
52
|
msg = (
|
46
|
-
f"
|
47
|
-
|
48
|
-
|
49
|
-
|
53
|
+
f"Dependencies cannot be solved. Missing dependencies:\n{missing_by_module}"
|
54
|
+
)
|
55
|
+
super().__init__(msg)
|
56
|
+
|
57
|
+
|
58
|
+
class CircularDependencyError(Exception):
|
59
|
+
"""Raised when dependencies cannot be sorted topologically.
|
60
|
+
|
61
|
+
This typically indicates circular dependencies in model components.
|
62
|
+
"""
|
63
|
+
|
64
|
+
def __init__(
|
65
|
+
self,
|
66
|
+
missing: dict[str, set[str]],
|
67
|
+
) -> None:
|
68
|
+
"""Initialise exception."""
|
69
|
+
missing_by_module = "\n".join(f"\t{k}: {v}" for k, v in missing.items())
|
70
|
+
msg = (
|
71
|
+
f"Exceeded max iterations on sorting dependencies.\n"
|
72
|
+
"Check if there are circular references. "
|
73
|
+
"Missing dependencies:\n"
|
74
|
+
f"{missing_by_module}"
|
50
75
|
)
|
51
76
|
super().__init__(msg)
|
52
77
|
|
@@ -119,6 +144,24 @@ def _invalidate_cache(method: Callable[Param, RetType]) -> Callable[Param, RetTy
|
|
119
144
|
return wrapper # type: ignore
|
120
145
|
|
121
146
|
|
147
|
+
def _check_if_is_sortable(
|
148
|
+
available: set[str],
|
149
|
+
elements: list[tuple[str, set[str]]],
|
150
|
+
) -> None:
|
151
|
+
all_available = available.copy()
|
152
|
+
for name, _ in elements:
|
153
|
+
all_available.add(name)
|
154
|
+
|
155
|
+
# Check if it can be sorted in the first place
|
156
|
+
not_solvable = {}
|
157
|
+
for name, args in elements:
|
158
|
+
if not args.issubset(all_available):
|
159
|
+
not_solvable[name] = sorted(args.difference(all_available))
|
160
|
+
|
161
|
+
if not_solvable:
|
162
|
+
raise MissingDependenciesError(not_solvable=not_solvable)
|
163
|
+
|
164
|
+
|
122
165
|
def _sort_dependencies(
|
123
166
|
available: set[str], elements: list[tuple[str, set[str]]]
|
124
167
|
) -> list[str]:
|
@@ -137,6 +180,8 @@ def _sort_dependencies(
|
|
137
180
|
"""
|
138
181
|
from queue import Empty, SimpleQueue
|
139
182
|
|
183
|
+
_check_if_is_sortable(available, elements)
|
184
|
+
|
140
185
|
order = []
|
141
186
|
# FIXME: what is the worst case here?
|
142
187
|
max_iterations = len(elements) ** 2
|
@@ -170,7 +215,10 @@ def _sort_dependencies(
|
|
170
215
|
unsorted.append(queue.get_nowait()[0])
|
171
216
|
except Empty:
|
172
217
|
break
|
173
|
-
|
218
|
+
|
219
|
+
mod_to_args: dict[str, set[str]] = dict(elements)
|
220
|
+
missing = {k: mod_to_args[k].difference(available) for k in unsorted}
|
221
|
+
raise CircularDependencyError(missing=missing)
|
174
222
|
return order
|
175
223
|
|
176
224
|
|
modelbase2/plot.py
CHANGED
@@ -818,7 +818,7 @@ def relative_label_distribution(
|
|
818
818
|
isos = mapper.get_isotopomers_of_at_position(name, i)
|
819
819
|
labels = cast(pd.DataFrame, concs.loc[:, isos])
|
820
820
|
total = concs.loc[:, f"{name}__total"]
|
821
|
-
ax.plot(labels.index, (labels.sum(axis=1) / total), label=f"C{i+1}")
|
821
|
+
ax.plot(labels.index, (labels.sum(axis=1) / total), label=f"C{i + 1}")
|
822
822
|
ax.set_title(name)
|
823
823
|
ax.legend()
|
824
824
|
else:
|
@@ -827,6 +827,6 @@ def relative_label_distribution(
|
|
827
827
|
):
|
828
828
|
ax.plot(concs.index, concs.loc[:, isos])
|
829
829
|
ax.set_title(name)
|
830
|
-
ax.legend([f"C{i+1}" for i in range(len(isos))])
|
830
|
+
ax.legend([f"C{i + 1}" for i in range(len(isos))])
|
831
831
|
|
832
832
|
return fig, axs
|
modelbase2/sbml/_import.py
CHANGED
@@ -507,7 +507,11 @@ def _codgen(name: str, sbml: Parser) -> Path:
|
|
507
507
|
|
508
508
|
# Initial assignments
|
509
509
|
initial_assignment_order = _sort_dependencies(
|
510
|
-
available=set(sbml.initial_assignment)
|
510
|
+
available=set(sbml.initial_assignment)
|
511
|
+
^ set(parameters)
|
512
|
+
^ set(variables)
|
513
|
+
^ set(sbml.derived)
|
514
|
+
| {"time"},
|
511
515
|
elements=[(k, set(v.args)) for k, v in sbml.initial_assignment.items()],
|
512
516
|
)
|
513
517
|
|
@@ -6,13 +6,13 @@ modelbase2/label_map.py,sha256=LUwcOHQWiGfBGV5XUmPM_SOwM9IyDVcQVJ11DPfVpAo,17774
|
|
6
6
|
modelbase2/linear_label_map.py,sha256=gA8CHxcehgtI6ovwZ9qNUPDvxfqbO1J1kBC_mltD4TY,10225
|
7
7
|
modelbase2/mc.py,sha256=zlDL7e_udpIMRhSjfFJo5AwkigD0B_3H2rQxyelBuzI,16285
|
8
8
|
modelbase2/mca.py,sha256=nMS2VnzR2VEujCFUaj9WL82CNd-oxTb3jCHP8IlJvxA,8845
|
9
|
-
modelbase2/model.py,sha256=
|
9
|
+
modelbase2/model.py,sha256=d-iAu64oxVgH9QgNYhNnJnrISic_U1Z5hX6ij6eDqh0,55260
|
10
10
|
modelbase2/nnarchitectures.py,sha256=OA1X4UHrn7gsLuuqxK6Dhv5aiKnQflhHezYCUV-NuO8,4012
|
11
11
|
modelbase2/npe.py,sha256=o876zHjyfJelGijSmCL0vUBfWbIhcbQyyPkwp8hZ4NA,8743
|
12
12
|
modelbase2/parallel.py,sha256=kX4Td5YoovDwZp6kX_3cfO6QtHSS9ieJ0bMZiKs3Xv8,5002
|
13
13
|
modelbase2/parameterise.py,sha256=7VrYxrQv0visraqUthWSnWfx-cxh2evlXbszIY5031U,690
|
14
14
|
modelbase2/paths.py,sha256=uatKXDa79uniUB2Z3dr8eBJVuUPXDI-o_bf-DqPKq1Y,1039
|
15
|
-
modelbase2/plot.py,sha256=
|
15
|
+
modelbase2/plot.py,sha256=72Oivv-jsCF9J9U7Uli15p5SnuEHSnHRXCaRP8uUaJo,22724
|
16
16
|
modelbase2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
17
|
modelbase2/scan.py,sha256=PvWZA4EgNS0JVMvm87bF72hSmhvo6O2KGg4vRzxve_8,18104
|
18
18
|
modelbase2/scope.py,sha256=4twnEh8LrTmlLE-uRvubVkE3SSWejlLvtBzTCPqG3Aw,3710
|
@@ -21,26 +21,26 @@ modelbase2/surrogates.py,sha256=Dk-YEXb-ot22W3r5Bl3rxApbCyvNdBnNCvRi_1f_NnA,9276
|
|
21
21
|
modelbase2/types.py,sha256=N74pWUZDcGlSMfDkjqqwHn5dkozlqgS6Wqg-58YKdvg,9904
|
22
22
|
modelbase2/experimental/__init__.py,sha256=IzgcQ7MtMII7n6cg1PMp-oZm06CNVR19ax2exvb9Ny0,444
|
23
23
|
modelbase2/experimental/_backup.py,sha256=As-L75tMQjWfkheRPk8xcroQPKDsSSejBJ2dXqPXmVo,46644
|
24
|
-
modelbase2/experimental/codegen.py,sha256=
|
24
|
+
modelbase2/experimental/codegen.py,sha256=i0soAT64oMBILGsWonoSSVkYMWOcCTY4RJ4TZoYlTos,6962
|
25
25
|
modelbase2/experimental/diff.py,sha256=e7fjD9kqxkRUNxSevbAznd5cOlEdWJ6pj0y7Kd5KKrw,8973
|
26
26
|
modelbase2/experimental/notes.md,sha256=YlM2biTzub6jSlx-aDZaBYsvQcGwb7NHyVAbbl2acGE,238
|
27
27
|
modelbase2/experimental/strikepy.py,sha256=cKBs9InXR9mEPgx70Ynv0qkmAGfloksqinbpppTiC6U,19464
|
28
28
|
modelbase2/experimental/symbolic.py,sha256=QT82TSW42RSVsvXK2WTQW1XluXnflWzrHbx6RFr_YmY,9953
|
29
|
-
modelbase2/experimental/tex.py,sha256=
|
29
|
+
modelbase2/experimental/tex.py,sha256=q9k9NfQucUhYzNjAKkroU9XnBcfdegPK6h3DHhkfGOg,13618
|
30
30
|
modelbase2/integrators/__init__.py,sha256=kqmV6a0TRyLGR_XqbyAI652AfptYnXAUpqbSFg0CpP8,450
|
31
31
|
modelbase2/integrators/int_assimulo.py,sha256=VEQIZFZcEovLPy8i_jR8H8XcxBRQoRVmNzzCYzInPc0,4611
|
32
32
|
modelbase2/integrators/int_scipy.py,sha256=-_9MS55eTc9jI7tk-3X49p-c7zrydoXaCCvDTn7Tybw,4334
|
33
33
|
modelbase2/sbml/__init__.py,sha256=FBaQsVvrVc7QbCBXuG9tZOdSzHcqmmsaRbFx80rxrac,231
|
34
34
|
modelbase2/sbml/_data.py,sha256=XwT1sSxn6KLTXYMbk4ORbEAEgZhQDBfoyrjMBDAoY_s,1135
|
35
35
|
modelbase2/sbml/_export.py,sha256=9BLD3Qz86vlfDTZXwOnNOSVWq8mHrJoQjQmKJRZL_Wo,20285
|
36
|
-
modelbase2/sbml/_import.py,sha256=
|
36
|
+
modelbase2/sbml/_import.py,sha256=1hP3xSktmbNic5asyk-b7L-FYQccEYvGAPchuLT4gqE,21586
|
37
37
|
modelbase2/sbml/_mathml.py,sha256=bNk9RQ_NQFDhY1R354p-gwqqHaIiyAwZ1xLPHHhiguQ,24436
|
38
38
|
modelbase2/sbml/_name_conversion.py,sha256=XK9DEyzhrD0GBBwwjK9RA0yORrDX5c-Uvx0VtKMR5rA,1325
|
39
39
|
modelbase2/sbml/_unit_conversion.py,sha256=dW_I6_Ou09ccwnp6LIdrPriIQnQUK5lJcjzM2Fawm6U,1927
|
40
40
|
modelbase2/surrogates/__init__.py,sha256=N_iXERECKvmrHiihwnyQEKOSBsmlGEuQhEotn-mWKdk,924
|
41
41
|
modelbase2/surrogates/_poly.py,sha256=zjlNL4iYR9G51gjvZPHe3CAYF-tgACGdIBe4QUYXLQk,3110
|
42
42
|
modelbase2/surrogates/_torch.py,sha256=CBS_3JzSgI2-xQrbq9CIXY0fJQsxbhBnWkG2TQyj7Zs,5885
|
43
|
-
modelbase2-0.
|
44
|
-
modelbase2-0.
|
45
|
-
modelbase2-0.
|
46
|
-
modelbase2-0.
|
43
|
+
modelbase2-0.5.0.dist-info/METADATA,sha256=plD8PQFIOOvu2jENW3PLVROFUOuSrXElAj6knn0YDeo,3344
|
44
|
+
modelbase2-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
45
|
+
modelbase2-0.5.0.dist-info/licenses/LICENSE,sha256=qvG2VolmSkrcocL34V1ieOx-Rn-fpVcUbb25gHzVgZw,35079
|
46
|
+
modelbase2-0.5.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|