modelbase2 0.1.53__tar.gz → 0.1.55__tar.gz

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 (22) hide show
  1. {modelbase2-0.1.53 → modelbase2-0.1.55}/PKG-INFO +1 -1
  2. {modelbase2-0.1.53 → modelbase2-0.1.55}/pyproject.toml +4 -1
  3. {modelbase2-0.1.53 → modelbase2-0.1.55}/setup.py +1 -1
  4. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/core/algebraic_module_container.py +12 -5
  5. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/core/constant_container.py +6 -2
  6. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/core/name_container.py +3 -2
  7. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/core/reaction_container.py +7 -3
  8. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/ode/integrator.py +1 -2
  9. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/ode/mca.py +12 -4
  10. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/ode/model.py +18 -6
  11. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/ode/simulator.py +13 -5
  12. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/utils/plotting.py +11 -5
  13. {modelbase2-0.1.53 → modelbase2-0.1.55}/LICENSE +0 -0
  14. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/__init__.py +0 -0
  15. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/core/__init__.py +0 -0
  16. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/core/data.py +0 -0
  17. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/core/utils.py +0 -0
  18. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/core/variable_container.py +0 -0
  19. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/ode/__init__.py +1 -1
  20. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/py.typed +0 -0
  21. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/types.py +0 -0
  22. {modelbase2-0.1.53 → modelbase2-0.1.55}/src/modelbase2/utils/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modelbase2
3
- Version: 0.1.53
3
+ Version: 0.1.55
4
4
  Summary: A package to build metabolic models
5
5
  Home-page: https://gitlab.com/qtb-hhu/modelbase-software
6
6
  License: GPL-3.0-or-later
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "modelbase2"
3
- version = "0.1.53"
3
+ version = "0.1.55"
4
4
  description = "A package to build metabolic models"
5
5
  license = "GPL-3.0-or-later"
6
6
  authors = ["Marvin van Aalst <marvin.vanaalst@gmail.com>", "Oliver Ebenhöh <oliver.ebenhoeh@hhu.de>"]
@@ -60,6 +60,9 @@ build-backend = "poetry.core.masonry.api"
60
60
  line-length = 90
61
61
  target-version = ['py310']
62
62
 
63
+ [tool.bandit]
64
+ skips = ["B101", "B301", "B403", "B404", "B603", "B607"]
65
+
63
66
  [tool.isort]
64
67
  profile = "black"
65
68
  src_paths = ["src", "tests"]
@@ -25,7 +25,7 @@ install_requires = \
25
25
 
26
26
  setup_kwargs = {
27
27
  'name': 'modelbase2',
28
- 'version': '0.1.53',
28
+ 'version': '0.1.55',
29
29
  'description': 'A package to build metabolic models',
30
30
  'long_description': 'None',
31
31
  'author': 'Marvin van Aalst',
@@ -1,12 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
- import numpy as np
4
+ from ..types import Array
5
5
  from .data import AlgebraicModule, ModuleFunction
6
6
  from dataclasses import dataclass, field
7
7
  from queue import Empty, SimpleQueue
8
8
  from typing import Iterable, Iterator, Optional, cast
9
- from ..types import Array
10
9
 
11
10
  logger = logging.getLogger(__name__)
12
11
 
@@ -19,7 +18,9 @@ class AlgebraicModuleContainer:
19
18
  def __iter__(self) -> Iterator[AlgebraicModule]:
20
19
  return iter(self.modules.values())
21
20
 
22
- def _sort_algebraic_modules(self, available_args: set[str], max_iterations: int = 10_000) -> None:
21
+ def _sort_algebraic_modules(
22
+ self, available_args: set[str], max_iterations: int = 10_000
23
+ ) -> None:
23
24
  module_order = []
24
25
  modules_to_sort: SimpleQueue[tuple[str, AlgebraicModule]] = SimpleQueue()
25
26
  for k, v in self.modules.items():
@@ -49,7 +50,11 @@ class AlgebraicModuleContainer:
49
50
  self.module_order = module_order
50
51
 
51
52
  def get_derived_variables(self) -> list[str]:
52
- return [variable for module in self.modules.values() for variable in module.derived_variables]
53
+ return [
54
+ variable
55
+ for module in self.modules.values()
56
+ for variable in module.derived_variables
57
+ ]
53
58
 
54
59
  def add(
55
60
  self,
@@ -116,7 +121,9 @@ class AlgebraicModuleContainer:
116
121
  module = self.modules[name]
117
122
  # values = np.array(module.function(*(args[arg] for arg in module.args)), dtype=float)
118
123
  # values = values.reshape((len(module.derived_variables), -1))
119
- _values = cast(Iterable[Array], module.function(*(args[arg] for arg in module.args)))
124
+ _values = cast(
125
+ Iterable[Array], module.function(*(args[arg] for arg in module.args))
126
+ )
120
127
  values = dict(zip(module.derived_variables, _values))
121
128
  derived_variables |= values
122
129
  args |= values
@@ -34,7 +34,9 @@ class ConstantContainer:
34
34
 
35
35
  def update_basic(self, name: str, value: float, update_derived: bool = True) -> None:
36
36
  if name not in self.constants:
37
- raise KeyError(f"Constant {name} is not in the model. You have to add it first")
37
+ raise KeyError(
38
+ f"Constant {name} is not in the model. You have to add it first"
39
+ )
38
40
  self.constants[name].value = value
39
41
  self.values[name] = value
40
42
  if name in self._derived_from_constants and update_derived:
@@ -80,7 +82,9 @@ class ConstantContainer:
80
82
  def _update_derived_constant_values(self) -> None:
81
83
  for name in self._derived_constant_order:
82
84
  derived_constant = self.derived_constants[name]
83
- value = derived_constant.function(*(self.values[i] for i in derived_constant.args))
85
+ value = derived_constant.function(
86
+ *(self.values[i] for i in derived_constant.args)
87
+ )
84
88
  self.values[name] = value
85
89
 
86
90
  def add_derived(self, constant: DerivedConstant, update_derived: bool = True) -> None:
@@ -13,13 +13,14 @@ class NameContainer:
13
13
 
14
14
  def add(self, name: str, element_type: str) -> None:
15
15
  if (old_type := self.names.get(name)) is not None:
16
- raise KeyError(f"Cannot add {element_type} {name}, as there already exists a {old_type} with that name.")
16
+ raise KeyError(
17
+ f"Cannot add {element_type} {name}, as there already exists a {old_type} with that name."
18
+ )
17
19
 
18
20
  logger.info(f"Adding name {name}")
19
21
  self.names[name] = element_type
20
22
 
21
23
  def remove(self, name: str) -> None:
22
-
23
24
  logger.info(f"Removing name {name}")
24
25
  del self.names[name]
25
26
 
@@ -3,10 +3,10 @@ from __future__ import annotations
3
3
  import logging
4
4
  import numpy as np
5
5
  import pandas as pd
6
+ from ..types import Array
6
7
  from .data import DerivedStoichiometry, RateFunction, Reaction, StoichiometryByVariable
7
8
  from dataclasses import dataclass, field
8
9
  from typing import Optional
9
- from ..types import Array
10
10
 
11
11
  logger = logging.getLogger()
12
12
 
@@ -14,7 +14,9 @@ logger = logging.getLogger()
14
14
  @dataclass
15
15
  class ReactionContainer:
16
16
  reactions: dict[str, Reaction] = field(default_factory=dict)
17
- stoichiometries_by_variables: dict[str, StoichiometryByVariable] = field(default_factory=dict)
17
+ stoichiometries_by_variables: dict[str, StoichiometryByVariable] = field(
18
+ default_factory=dict
19
+ )
18
20
 
19
21
  def set_stoichiometry(self, variable: str, reaction: str, factor: float) -> None:
20
22
  self.stoichiometries_by_variables.setdefault(variable, {})[reaction] = factor
@@ -23,7 +25,9 @@ class ReactionContainer:
23
25
  for variable, factor in reaction.stoichiometry.items():
24
26
  self.set_stoichiometry(variable, name, factor)
25
27
 
26
- def update_derived_stoichiometry(self, name: str, reaction: Reaction, constants: dict[str, float]) -> None:
28
+ def update_derived_stoichiometry(
29
+ self, name: str, reaction: Reaction, constants: dict[str, float]
30
+ ) -> None:
27
31
  for variable, derived_stoich in reaction.derived_stoichiometry.items():
28
32
  factor = derived_stoich.function(*(constants[i] for i in derived_stoich.args))
29
33
  self.set_stoichiometry(variable, name, factor)
@@ -1,13 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import numpy as np
4
- import pandas as pd
4
+ from ..types import Array
5
5
  from assimulo.problem import Explicit_Problem # type: ignore
6
6
  from assimulo.solvers import CVode # type: ignore
7
7
  from assimulo.solvers.sundials import CVodeError # type: ignore
8
8
  from dataclasses import dataclass
9
9
  from typing import Callable, Optional, cast
10
- from ..types import Array
11
10
 
12
11
 
13
12
  @dataclass
@@ -59,7 +59,9 @@ def get_variable_elasticities(
59
59
  Also called epsilon-elasticities. Not in steady state!
60
60
  """
61
61
  stoichiometries = m.get_stoichiometries().columns
62
- elasticities = np.full(shape=(len(variables), len(stoichiometries)), fill_value=np.nan)
62
+ elasticities = np.full(
63
+ shape=(len(variables), len(stoichiometries)), fill_value=np.nan
64
+ )
63
65
  for i, variable in enumerate(variables):
64
66
  elasticities[i] = get_variable_elasticity(
65
67
  m=m,
@@ -105,7 +107,9 @@ def get_constant_elasticities(
105
107
  Also called pi-elasticities. Not in steady state!
106
108
  """
107
109
  stoichiometries = m.get_stoichiometries().columns
108
- elasticities = np.full(shape=(len(constants), len(stoichiometries)), fill_value=np.nan)
110
+ elasticities = np.full(
111
+ shape=(len(constants), len(stoichiometries)), fill_value=np.nan
112
+ )
109
113
  for i, constant in enumerate(constants):
110
114
  elasticities[i] = get_constant_elasticity(
111
115
  m=m,
@@ -154,8 +158,12 @@ def _get_response_coefficients_single_constant(
154
158
  flux_resp_coef = (fluxes[0] - fluxes[1]) / (2 * displacement * old_value)
155
159
 
156
160
  return (
157
- pd.Series(conc_resp_coef * y_ss_norm, index=list(y_full.keys())).replace([np.inf, -np.inf], np.nan),
158
- pd.Series(flux_resp_coef * fluxes_norm, index=list(m.reactions)).replace([np.inf, -np.inf], np.nan),
161
+ pd.Series(conc_resp_coef * y_ss_norm, index=list(y_full.keys())).replace(
162
+ [np.inf, -np.inf], np.nan
163
+ ),
164
+ pd.Series(flux_resp_coef * fluxes_norm, index=list(m.reactions)).replace(
165
+ [np.inf, -np.inf], np.nan
166
+ ),
159
167
  )
160
168
 
161
169
 
@@ -62,13 +62,17 @@ def _sort_derived_compounds(m: Model, max_iterations: int = 10_000) -> list[str]
62
62
  except Empty:
63
63
  break
64
64
 
65
- raise ValueError("Exceeded max iterations on sorting. Check if there are circular references.")
65
+ raise ValueError(
66
+ "Exceeded max iterations on sorting. Check if there are circular references."
67
+ )
66
68
  return order
67
69
 
68
70
 
69
71
  @dataclass
70
72
  class Model:
71
- _algebraic_modules: AlgebraicModuleContainer = field(default_factory=AlgebraicModuleContainer)
73
+ _algebraic_modules: AlgebraicModuleContainer = field(
74
+ default_factory=AlgebraicModuleContainer
75
+ )
72
76
  _variables: VariableContainer = field(default_factory=VariableContainer)
73
77
  _constants: ConstantContainer = field(default_factory=ConstantContainer)
74
78
  _reactions: ReactionContainer = field(default_factory=ReactionContainer)
@@ -310,7 +314,9 @@ class Model:
310
314
  derived_variables = old_module.derived_variables
311
315
  if args is None:
312
316
  args = old_module.args
313
- self.add_algebraic_module(AlgebraicModule(name, function, derived_variables, args))
317
+ self.add_algebraic_module(
318
+ AlgebraicModule(name, function, derived_variables, args)
319
+ )
314
320
 
315
321
  self._algebraic_modules.update(
316
322
  name,
@@ -378,7 +384,9 @@ class Model:
378
384
  args |= self._algebraic_modules.get_values_float(args)
379
385
  return args
380
386
 
381
- def get_derived_variables(self, variables: dict[str, float], time: float = 0.0) -> dict[str, float]:
387
+ def get_derived_variables(
388
+ self, variables: dict[str, float], time: float = 0.0
389
+ ) -> dict[str, float]:
382
390
  args = variables | self.constant_values | {"time": time}
383
391
  return self._algebraic_modules.get_values_float(args)
384
392
 
@@ -435,7 +443,9 @@ class Model:
435
443
  else:
436
444
  raise NotImplementedError(f"Unknown return type {return_type}")
437
445
 
438
- def get_right_hand_side(self, variables: dict[str, float], time: float = 0.0) -> dict[str, float]:
446
+ def get_right_hand_side(
447
+ self, variables: dict[str, float], time: float = 0.0
448
+ ) -> dict[str, float]:
439
449
  fluxes = self.get_fluxes(variables, time=time)
440
450
  return self._reactions.get_right_hand_side_float(fluxes)
441
451
 
@@ -451,7 +461,9 @@ class Model:
451
461
  old.add_derived_parameter(k, dc.function, dc.args)
452
462
 
453
463
  for k, am in self.algebraic_modules.items():
454
- old.add_algebraic_module_from_args(k, am.function, am.derived_variables, am.args)
464
+ old.add_algebraic_module_from_args(
465
+ k, am.function, am.derived_variables, am.args
466
+ )
455
467
 
456
468
  for r in self.reactions.values():
457
469
  old.add_reaction_from_args(r.name, r.function, r.stoichiometry, r.args)
@@ -3,11 +3,11 @@ from __future__ import annotations
3
3
  import logging
4
4
  import numpy as np
5
5
  import pandas as pd
6
+ from ..types import Array
6
7
  from .integrator import Assimulo
7
8
  from .model import Model
8
9
  from dataclasses import dataclass, field
9
10
  from typing import Any, Optional, Type
10
- from ..types import Array
11
11
 
12
12
  logger = logging.getLogger()
13
13
 
@@ -90,8 +90,12 @@ class Simulator:
90
90
  self.results.append(res)
91
91
  return res
92
92
 
93
- def simulate_to_steady_state(self, tolerance: float = 1e-6) -> Optional[dict[str, float]]:
94
- if (integration := self.integrator.integrate_to_steady_state(tolerance)) is not None:
93
+ def simulate_to_steady_state(
94
+ self, tolerance: float = 1e-6
95
+ ) -> Optional[dict[str, float]]:
96
+ if (
97
+ integration := self.integrator.integrate_to_steady_state(tolerance)
98
+ ) is not None:
95
99
  return dict(zip(self.model.stoichiometries, integration))
96
100
  else:
97
101
  logger.warning("Simulation failed")
@@ -109,7 +113,9 @@ class Simulator:
109
113
  ) -> dict[str, Array]:
110
114
  return self.model._algebraic_modules.get_values_array(args)
111
115
 
112
- def _get_result_all_variables(self, result: SimulationResult, constants: dict[str, Array]) -> dict[str, Array]:
116
+ def _get_result_all_variables(
117
+ self, result: SimulationResult, constants: dict[str, Array]
118
+ ) -> dict[str, Array]:
113
119
  args = result.values | constants | {"time": result.time}
114
120
  return result.values | self._get_result_derived_variables(args)
115
121
 
@@ -124,7 +130,9 @@ class Simulator:
124
130
  for result in self.results:
125
131
  full_results.append(
126
132
  SimulationResult(
127
- values=self._get_result_all_variables(result, self._get_result_constants(result)),
133
+ values=self._get_result_all_variables(
134
+ result, self._get_result_constants(result)
135
+ ),
128
136
  time=result.time,
129
137
  constants=result.constants,
130
138
  )
@@ -5,11 +5,11 @@ import math
5
5
  import matplotlib.pyplot as plt
6
6
  import numpy as np
7
7
  import pandas as pd
8
+ from ..types import Axes, Figure
8
9
  from matplotlib.collections import QuadMesh
9
10
  from matplotlib.colors import LogNorm, Normalize, SymLogNorm
10
11
  from matplotlib.colors import colorConverter as _colorConverter
11
12
  from typing import Any, Iterable, Optional, Sized, Union
12
- from ..types import Figure, Axes
13
13
 
14
14
 
15
15
  def _get_plot_kwargs(
@@ -191,7 +191,10 @@ def plot_grid(
191
191
  """Plot simulation results as a grid."""
192
192
  if ncols is None:
193
193
  _, ncols = min(
194
- ((math.ceil(len(plot_groups) / i) * i - len(plot_groups), i) for i in range(2, 6)),
194
+ (
195
+ (math.ceil(len(plot_groups) / i) * i - len(plot_groups), i)
196
+ for i in range(2, 6)
197
+ ),
195
198
  key=lambda x: (x[0], -x[1]),
196
199
  )
197
200
  nrows = math.ceil(len(plot_groups) / ncols)
@@ -278,7 +281,6 @@ def relative_luminance(color: list[float]) -> float:
278
281
 
279
282
 
280
283
  def get_norm(vmin: float, vmax: float) -> plt.Normalize:
281
-
282
284
  if vmax < 1000 and vmin > -1000:
283
285
  norm = Normalize(vmin=vmin, vmax=vmax)
284
286
  elif vmin <= 0:
@@ -348,8 +350,12 @@ def heatmap_from_dataframe(
348
350
  text_kwargs = {"ha": "center", "va": "center"}
349
351
  hm.update_scalarmappable() # So that get_facecolor is an array
350
352
  xpos, ypos = np.meshgrid(np.arange(len(columns)), np.arange(len(rows)))
351
- for x, y, val, color in zip(xpos.flat, ypos.flat, hm.get_array(), hm.get_facecolor()):
352
- text_kwargs["color"] = "black" if relative_luminance(color) > 0.45 else "white"
353
+ for x, y, val, color in zip(
354
+ xpos.flat, ypos.flat, hm.get_array(), hm.get_facecolor()
355
+ ):
356
+ text_kwargs["color"] = (
357
+ "black" if relative_luminance(color) > 0.45 else "white"
358
+ )
353
359
  if sci_annotation_bounds[0] < abs(val) <= sci_annotation_bounds[1]:
354
360
  val_text = f"{val:.{annotation_style}}"
355
361
  else:
File without changes
@@ -7,7 +7,7 @@ __all__ = [
7
7
  "mca",
8
8
  ]
9
9
 
10
+ from . import mca
10
11
  from .integrator import Assimulo
11
12
  from .model import Model
12
13
  from .simulator import Simulator
13
- from . import mca