modelbase2 0.5.0__py3-none-any.whl → 0.7.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.
@@ -1,14 +1,18 @@
1
1
  from collections.abc import Iterable
2
2
  from dataclasses import dataclass
3
+ from typing import Literal
3
4
 
4
5
  import numpy as np
5
6
  import pandas as pd
6
7
  from numpy import polynomial
7
- from typing import Union, Literal
8
8
 
9
9
  from modelbase2.types import AbstractSurrogate, ArrayLike
10
10
 
11
- __all__ = ["PolySurrogate", "PolynomialExpansion", "train_polynomial_surrogate"]
11
+ __all__ = [
12
+ "PolySurrogate",
13
+ "PolynomialExpansion",
14
+ "train_polynomial_surrogate",
15
+ ]
12
16
 
13
17
  # define custom type
14
18
  PolynomialExpansion = (
@@ -160,7 +160,7 @@ def train_torch_surrogate(
160
160
  if approximator is None:
161
161
  approximator = MLP(
162
162
  n_inputs=len(features.columns),
163
- layers=[50, 50, len(targets.columns)],
163
+ neurons_per_layer=[50, 50, len(targets.columns)],
164
164
  ).to(device)
165
165
 
166
166
  optimizer = optimimzer_cls(approximator.parameters())
modelbase2/types.py CHANGED
@@ -127,13 +127,13 @@ class IntegratorProtocol(Protocol):
127
127
  *,
128
128
  t_end: float,
129
129
  steps: int | None = None,
130
- ) -> tuple[ArrayLike | None, ArrayLike | None]:
130
+ ) -> tuple[Array | None, ArrayLike | None]:
131
131
  """Integrate the system."""
132
132
  ...
133
133
 
134
134
  def integrate_time_course(
135
135
  self, *, time_points: ArrayLike
136
- ) -> tuple[ArrayLike | None, ArrayLike | None]:
136
+ ) -> tuple[Array | None, ArrayLike | None]:
137
137
  """Integrate the system over a time course."""
138
138
  ...
139
139
 
@@ -147,31 +147,96 @@ class IntegratorProtocol(Protocol):
147
147
  ...
148
148
 
149
149
 
150
- @dataclass(slots=True)
150
+ @dataclass(kw_only=True, slots=True)
151
151
  class Derived:
152
152
  """Container for a derived value."""
153
153
 
154
+ name: str
154
155
  fn: RateFn
155
156
  args: list[str]
156
- math: str | None = None
157
157
 
158
+ def calculate(self, dependent: dict[str, float]) -> float:
159
+ """Calculate the derived value.
158
160
 
159
- @dataclass(slots=True)
161
+ Args:
162
+ dependent: Dictionary of dependent variables.
163
+
164
+ Returns:
165
+ The calculated derived value.
166
+
167
+ """
168
+ return cast(float, self.fn(*(dependent[arg] for arg in self.args)))
169
+
170
+ def calculate_inpl(self, dependent: dict[str, float]) -> None:
171
+ """Calculate the derived value in place.
172
+
173
+ Args:
174
+ dependent: Dictionary of dependent variables.
175
+
176
+ """
177
+ dependent[self.name] = cast(
178
+ float, self.fn(*(dependent[arg] for arg in self.args))
179
+ )
180
+
181
+ def calculate_inpl_time_course(self, dependent: pd.DataFrame) -> None:
182
+ """Calculate the derived value in place.
183
+
184
+ Args:
185
+ dependent: Dictionary of dependent variables.
186
+
187
+ """
188
+ dependent[self.name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
189
+
190
+
191
+ @dataclass(kw_only=True, slots=True)
160
192
  class Readout:
161
193
  """Container for a readout."""
162
194
 
195
+ name: str
163
196
  fn: RateFn
164
197
  args: list[str]
165
198
 
199
+ def calculate(self, dependent: dict[str, float]) -> float:
200
+ """Calculate the derived value.
201
+
202
+ Args:
203
+ dependent: Dictionary of dependent variables.
204
+
205
+ Returns:
206
+ The calculated derived value.
207
+
208
+ """
209
+ return cast(float, self.fn(*(dependent[arg] for arg in self.args)))
210
+
211
+ def calculate_inpl(self, dependent: dict[str, float]) -> None:
212
+ """Calculate the readout in place.
213
+
214
+ Args:
215
+ dependent: Dictionary of dependent variables.
216
+
217
+ """
218
+ dependent[self.name] = cast(
219
+ float, self.fn(*(dependent[arg] for arg in self.args))
220
+ )
221
+
222
+ def calculate_inpl_time_course(self, dependent: pd.DataFrame) -> None:
223
+ """Calculate the derived value in place.
166
224
 
167
- @dataclass(slots=True)
225
+ Args:
226
+ dependent: Dictionary of dependent variables.
227
+
228
+ """
229
+ dependent[self.name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
230
+
231
+
232
+ @dataclass(kw_only=True, slots=True)
168
233
  class Reaction:
169
234
  """Container for a reaction."""
170
235
 
236
+ name: str
171
237
  fn: RateFn
172
238
  stoichiometry: Mapping[str, float | Derived]
173
239
  args: list[str]
174
- math: str | None = None
175
240
 
176
241
  def get_modifiers(self, model: Model) -> list[str]:
177
242
  """Get the modifiers of the reaction."""
@@ -180,8 +245,44 @@ class Reaction:
180
245
 
181
246
  return [k for k in self.args if k in include and k not in exclude]
182
247
 
248
+ def calculate(self, dependent: dict[str, float]) -> float:
249
+ """Calculate the derived value.
250
+
251
+ Args:
252
+ dependent: Dictionary of dependent variables.
253
+
254
+ Returns:
255
+ The calculated derived value.
256
+
257
+ """
258
+ return cast(float, self.fn(*(dependent[arg] for arg in self.args)))
259
+
260
+ def calculate_inpl(self, dependent: dict[str, float]) -> None:
261
+ """Calculate the reaction in place.
262
+
263
+ Args:
264
+ dependent: Dictionary of dependent variables.
265
+
266
+ """
267
+ dependent[self.name] = cast(
268
+ float, self.fn(*(dependent[arg] for arg in self.args))
269
+ )
183
270
 
184
- @dataclass(slots=True)
271
+ def calculate_inpl_time_course(self, dependent: pd.DataFrame) -> None:
272
+ """Calculate the derived value in place.
273
+
274
+ Args:
275
+ dependent: Dictionary of dependent variables.
276
+
277
+ """
278
+ try:
279
+ dependent[self.name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
280
+ except ValueError: # e.g. numpy.where
281
+ sub = dependent.loc[:, self.args].to_numpy()
282
+ dependent[self.name] = [self.fn(*row) for row in sub]
283
+
284
+
285
+ @dataclass(kw_only=True, slots=True)
185
286
  class ResponseCoefficients:
186
287
  """Container for response coefficients."""
187
288
 
@@ -198,7 +299,7 @@ class ResponseCoefficients:
198
299
  return pd.concat((self.concs, self.fluxes), axis=1)
199
300
 
200
301
 
201
- @dataclass(slots=True)
302
+ @dataclass(kw_only=True, slots=True)
202
303
  class ResponseCoefficientsByPars:
203
304
  """Container for response coefficients by parameter."""
204
305
 
@@ -216,7 +317,7 @@ class ResponseCoefficientsByPars:
216
317
  return pd.concat((self.concs, self.fluxes), axis=1)
217
318
 
218
319
 
219
- @dataclass(slots=True)
320
+ @dataclass(kw_only=True, slots=True)
220
321
  class SteadyStates:
221
322
  """Container for steady states."""
222
323
 
@@ -234,7 +335,7 @@ class SteadyStates:
234
335
  return pd.concat((self.concs, self.fluxes), axis=1)
235
336
 
236
337
 
237
- @dataclass(slots=True)
338
+ @dataclass(kw_only=True, slots=True)
238
339
  class McSteadyStates:
239
340
  """Container for Monte Carlo steady states."""
240
341
 
@@ -253,7 +354,7 @@ class McSteadyStates:
253
354
  return pd.concat((self.concs, self.fluxes), axis=1)
254
355
 
255
356
 
256
- @dataclass(slots=True)
357
+ @dataclass(kw_only=True, slots=True)
257
358
  class TimeCourseByPars:
258
359
  """Container for time courses by parameter."""
259
360
 
@@ -285,7 +386,7 @@ class TimeCourseByPars:
285
386
  return cast(pd.DataFrame, mean.unstack().T)
286
387
 
287
388
 
288
- @dataclass(slots=True)
389
+ @dataclass(kw_only=True, slots=True)
289
390
  class ProtocolByPars:
290
391
  """Container for protocols by parameter."""
291
392
 
@@ -348,14 +449,26 @@ class AbstractSurrogate:
348
449
  )
349
450
  )
350
451
 
452
+ def calculate_inpl(self, args: dict[str, float]) -> None:
453
+ """Predict outputs based on input data."""
454
+ args |= self.predict(np.array([args[arg] for arg in self.args]))
455
+
456
+ def calculate_inpl_time_course(self, args: pd.DataFrame) -> None:
457
+ """Predict outputs based on input data."""
458
+ args[list(self.stoichiometries)] = pd.DataFrame(
459
+ [self.predict(y) for y in args.loc[:, self.args].to_numpy()],
460
+ index=args.index,
461
+ dtype=float,
462
+ )
463
+
351
464
 
352
465
  @dataclass(kw_only=True)
353
466
  class MockSurrogate(AbstractSurrogate):
354
467
  """Mock surrogate model for testing purposes."""
355
468
 
356
- def predict_raw(
469
+ def predict(
357
470
  self,
358
471
  y: np.ndarray,
359
- ) -> np.ndarray:
472
+ ) -> dict[str, float]:
360
473
  """Predict outputs based on input data."""
361
- return y
474
+ return dict(zip(self.stoichiometries, y, strict=True))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modelbase2
3
- Version: 0.5.0
3
+ Version: 0.7.0
4
4
  Summary: A package to build metabolic models
5
5
  Author-email: Marvin van Aalst <marvin.vanaalst@gmail.com>
6
6
  Maintainer-email: Marvin van Aalst <marvin.vanaalst@gmail.com>
@@ -60,6 +60,16 @@ Description-Content-Type: text/markdown
60
60
 
61
61
  # modelbase
62
62
 
63
+ [![pypi](https://img.shields.io/pypi/v/modelbase2.svg)](https://pypi.python.org/pypi/modelbase2)
64
+ [![docs][docs-badge]][docs]
65
+ ![License](https://img.shields.io/badge/license-GPL--3.0-blue?style=flat-square)
66
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
67
+ [![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
68
+ [![Downloads](https://pepy.tech/badge/modelbase2)](https://pepy.tech/project/modelbase2)
69
+
70
+ [docs-badge]: https://img.shields.io/badge/docs-main-green.svg?style=flat-square
71
+ [docs]: https://computational-biology-aachen.github.io/modelbase2/
72
+
63
73
  ## Installation
64
74
 
65
75
  You can install modelbase using pip: `pip install modelbase2`
@@ -0,0 +1,44 @@
1
+ modelbase2/__init__.py,sha256=hAbljI8oAskpz6qQph4YWNGPlUXI2chdtxFuUffhxYA,4068
2
+ modelbase2/distributions.py,sha256=i456B0KYKdiGwuoVjoj3rey5lKdJmu9EVvacnfWXHGA,8744
3
+ modelbase2/fit.py,sha256=uAMiSa4bnYxW5kdVDB2d61iV9uQGYuxKrLSiOX1IpTE,8185
4
+ modelbase2/fns.py,sha256=mlV44qL8H2lbtmopsKRFkLA6rFZOiQ1mPNr5S2smjHY,4604
5
+ modelbase2/label_map.py,sha256=LUwcOHQWiGfBGV5XUmPM_SOwM9IyDVcQVJ11DPfVpAo,17774
6
+ modelbase2/linear_label_map.py,sha256=6qs7SZIaiMcA0jRCdZXMe44lG7pBtKzYNMYSfNz2CfY,10317
7
+ modelbase2/mc.py,sha256=zlDL7e_udpIMRhSjfFJo5AwkigD0B_3H2rQxyelBuzI,16285
8
+ modelbase2/mca.py,sha256=AFXMOpV1dhPxHBdDOP3212qXM_ItonMOj8v3UAMK0J0,8869
9
+ modelbase2/model.py,sha256=YFzBOCuy53dvXLbeel0o4rAqw_rmRSUq8dL6ASltdSU,57136
10
+ modelbase2/nnarchitectures.py,sha256=vk0BYTssVMWyoLYQUBvj-Q4mVSukwhYP1uEzQCHrD9Q,4067
11
+ modelbase2/npe.py,sha256=G-GMpC6LFzHq8-Sk0b1IbbUOoT_xq5yJztjcq3JNDhc,8767
12
+ modelbase2/parallel.py,sha256=kX4Td5YoovDwZp6kX_3cfO6QtHSS9ieJ0bMZiKs3Xv8,5002
13
+ modelbase2/parameterise.py,sha256=2jMhhO-bHTFP_0kXercJekeATAZYBg5FrK1MQ_mWGpk,654
14
+ modelbase2/paths.py,sha256=uatKXDa79uniUB2Z3dr8eBJVuUPXDI-o_bf-DqPKq1Y,1039
15
+ modelbase2/plot.py,sha256=72Oivv-jsCF9J9U7Uli15p5SnuEHSnHRXCaRP8uUaJo,22724
16
+ modelbase2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ modelbase2/scan.py,sha256=ooBgRYovFkJL22Uaw5uv7yEhNuYGz5Png6naUpn8F7s,18098
18
+ modelbase2/simulator.py,sha256=syK_o8Xk2rIXVu3ZUe_BlWz2UNlzNLNbkI1qbaxmS38,19996
19
+ modelbase2/types.py,sha256=_V45vC8VPPAJuRtDHKUrglekzIDIM1zMuk7iF3GlXBU,13545
20
+ modelbase2/experimental/__init__.py,sha256=IzgcQ7MtMII7n6cg1PMp-oZm06CNVR19ax2exvb9Ny0,444
21
+ modelbase2/experimental/codegen.py,sha256=OI8sDeQjd7ShH8TAOq61IvNcWO0oQ1LF9lLW5p6Xwf0,6965
22
+ modelbase2/experimental/diff.py,sha256=yADvi_AKppO071bVBmq1Ej85BREXZu2K7kIRqr2FEyY,8962
23
+ modelbase2/experimental/notes.md,sha256=YlM2biTzub6jSlx-aDZaBYsvQcGwb7NHyVAbbl2acGE,238
24
+ modelbase2/experimental/source_tools.py,sha256=erdIVfF2q7TwS4v54AKLBGAiRhd_bIYxxjxsZ6MjfP0,735
25
+ modelbase2/experimental/strikepy.py,sha256=cKBs9InXR9mEPgx70Ynv0qkmAGfloksqinbpppTiC6U,19464
26
+ modelbase2/experimental/symbolic.py,sha256=wZuQAaykCsRabhxSy5Dl_VpG7u_EoOBCXLYCMGseZf4,11592
27
+ modelbase2/experimental/tex.py,sha256=geFwHt9xYgtudJiZsKGk-b_xCELuhFj0ANn0tOTe5dY,13624
28
+ modelbase2/integrators/__init__.py,sha256=kqmV6a0TRyLGR_XqbyAI652AfptYnXAUpqbSFg0CpP8,450
29
+ modelbase2/integrators/int_assimulo.py,sha256=FdNzh1zkXV7DFO10XCtIqJHicSlsRjc9Ixtr4LDQmOY,4610
30
+ modelbase2/integrators/int_scipy.py,sha256=twb3s3b1nAX7TKBmd2HT5p-lcSlhh5wMpFJANRXmpsQ,4348
31
+ modelbase2/sbml/__init__.py,sha256=FBaQsVvrVc7QbCBXuG9tZOdSzHcqmmsaRbFx80rxrac,231
32
+ modelbase2/sbml/_data.py,sha256=XwT1sSxn6KLTXYMbk4ORbEAEgZhQDBfoyrjMBDAoY_s,1135
33
+ modelbase2/sbml/_export.py,sha256=7I5TWkSmXZ1uPwlv5MuMP3OMS9dEOFTUQlcsrMtueJ0,19998
34
+ modelbase2/sbml/_import.py,sha256=K-SL3aUaefqxxR0daCErisJ_Nd9rKdCmtjVu4rXD0_k,22063
35
+ modelbase2/sbml/_mathml.py,sha256=bNk9RQ_NQFDhY1R354p-gwqqHaIiyAwZ1xLPHHhiguQ,24436
36
+ modelbase2/sbml/_name_conversion.py,sha256=XK9DEyzhrD0GBBwwjK9RA0yORrDX5c-Uvx0VtKMR5rA,1325
37
+ modelbase2/sbml/_unit_conversion.py,sha256=dW_I6_Ou09ccwnp6LIdrPriIQnQUK5lJcjzM2Fawm6U,1927
38
+ modelbase2/surrogates/__init__.py,sha256=N_iXERECKvmrHiihwnyQEKOSBsmlGEuQhEotn-mWKdk,924
39
+ modelbase2/surrogates/_poly.py,sha256=7T3xE7I4fKOxQY-bDnMG6WjMC5DHXeuvx-6vMi2fZbA,3118
40
+ modelbase2/surrogates/_torch.py,sha256=xNpkY4cfcy1cYVpAuEiKrh3ZuMWlzE07J-p2F7Q227Y,5896
41
+ modelbase2-0.7.0.dist-info/METADATA,sha256=6p81vMPYQk72L55UyQM2pjazgihWi_ymS1pSP8g89eE,4058
42
+ modelbase2-0.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
43
+ modelbase2-0.7.0.dist-info/licenses/LICENSE,sha256=qvG2VolmSkrcocL34V1ieOx-Rn-fpVcUbb25gHzVgZw,35079
44
+ modelbase2-0.7.0.dist-info/RECORD,,