mxlpy 0.14.0__py3-none-any.whl → 0.15.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/linear_label_map.py CHANGED
@@ -287,11 +287,11 @@ class LinearLabelMapper:
287
287
  stoichiometry = {}
288
288
  if substrate != "EXT":
289
289
  stoichiometry[substrate] = Derived(
290
- name=substrate, fn=_neg_one_div, args=[substrate.split("__")[0]]
290
+ fn=_neg_one_div, args=[substrate.split("__")[0]]
291
291
  )
292
292
  if product != "EXT":
293
293
  stoichiometry[product] = Derived(
294
- name=product, fn=_one_div, args=[product.split("__")[0]]
294
+ fn=_one_div, args=[product.split("__")[0]]
295
295
  )
296
296
 
297
297
  m.add_reaction(
@@ -326,9 +326,7 @@ class TexExport:
326
326
  parameters={gls.get(k, k): v for k, v in self.parameters.items()},
327
327
  variables={gls.get(k, k): v for k, v in self.variables.items()},
328
328
  derived={
329
- gls.get(k, k): Derived(
330
- name=k, fn=v.fn, args=[gls.get(i, i) for i in v.args]
331
- )
329
+ gls.get(k, k): Derived(fn=v.fn, args=[gls.get(i, i) for i in v.args])
332
330
  for k, v in self.derived.items()
333
331
  },
334
332
  reactions={
@@ -64,7 +64,7 @@ def generate_mxlpy_code(model: Model) -> str:
64
64
  )
65
65
  args = ", ".join(f'"{k}"' for k in stoich.args)
66
66
  stoich = ( # noqa: PLW2901
67
- f"""Derived(name="{var}", fn={fn.__name__}, args=[{args}])"""
67
+ f"""Derived(fn={fn.__name__}, args=[{args}])"""
68
68
  )
69
69
  stoichiometry.append(f""""{var}": {stoich}""")
70
70
 
mxlpy/model.py CHANGED
@@ -908,7 +908,7 @@ class Model:
908
908
 
909
909
  """
910
910
  self._insert_id(name=name, ctx="derived")
911
- self._derived[name] = Derived(name=name, fn=fn, args=args)
911
+ self._derived[name] = Derived(fn=fn, args=args)
912
912
  return self
913
913
 
914
914
  def get_derived_parameter_names(self) -> list[str]:
@@ -1058,12 +1058,10 @@ class Model:
1058
1058
  self._insert_id(name=name, ctx="reaction")
1059
1059
 
1060
1060
  stoich: dict[str, Derived | float] = {
1061
- k: Derived(name=k, fn=fns.constant, args=[v]) if isinstance(v, str) else v
1061
+ k: Derived(fn=fns.constant, args=[v]) if isinstance(v, str) else v
1062
1062
  for k, v in stoichiometry.items()
1063
1063
  }
1064
- self._reactions[name] = Reaction(
1065
- name=name, fn=fn, stoichiometry=stoich, args=args
1066
- )
1064
+ self._reactions[name] = Reaction(fn=fn, stoichiometry=stoich, args=args)
1067
1065
  return self
1068
1066
 
1069
1067
  def get_reaction_names(self) -> list[str]:
@@ -1112,9 +1110,7 @@ class Model:
1112
1110
 
1113
1111
  if stoichiometry is not None:
1114
1112
  stoich = {
1115
- k: Derived(name=k, fn=fns.constant, args=[v])
1116
- if isinstance(v, str)
1117
- else v
1113
+ k: Derived(fn=fns.constant, args=[v]) if isinstance(v, str) else v
1118
1114
  for k, v in stoichiometry.items()
1119
1115
  }
1120
1116
  rxn.stoichiometry = stoich
@@ -1188,7 +1184,7 @@ class Model:
1188
1184
 
1189
1185
  """
1190
1186
  self._insert_id(name=name, ctx="readout")
1191
- self._readouts[name] = Readout(name=name, fn=fn, args=args)
1187
+ self._readouts[name] = Readout(fn=fn, args=args)
1192
1188
  return self
1193
1189
 
1194
1190
  def get_readout_names(self) -> list[str]:
@@ -1354,7 +1350,7 @@ class Model:
1354
1350
 
1355
1351
  containers = self._derived | self._reactions | self._surrogates
1356
1352
  for name in cache.order:
1357
- containers[name].calculate_inpl(args)
1353
+ containers[name].calculate_inpl(name, args)
1358
1354
 
1359
1355
  return args
1360
1356
 
@@ -1399,8 +1395,8 @@ class Model:
1399
1395
  )
1400
1396
 
1401
1397
  if include_readouts:
1402
- for ro in self._readouts.values(): # FIXME: order?
1403
- ro.calculate_inpl(args)
1398
+ for name, ro in self._readouts.items(): # FIXME: order?
1399
+ ro.calculate_inpl(name, args)
1404
1400
 
1405
1401
  return pd.Series(args, dtype=float)
1406
1402
 
@@ -1449,7 +1445,7 @@ class Model:
1449
1445
 
1450
1446
  containers = self._derived | self._reactions | self._surrogates
1451
1447
  for name in cache.order:
1452
- containers[name].calculate_inpl_time_course(args)
1448
+ containers[name].calculate_inpl_time_course(name, args)
1453
1449
 
1454
1450
  if include_readouts:
1455
1451
  for name, ro in self._readouts.items():
mxlpy/simulator.py CHANGED
@@ -16,8 +16,10 @@ from typing import TYPE_CHECKING, Literal, Self, cast, overload
16
16
 
17
17
  import numpy as np
18
18
  import pandas as pd
19
+ from sympy import lambdify
19
20
 
20
21
  from mxlpy.integrators import DefaultIntegrator
22
+ from mxlpy.symbolic import to_symbolic_model
21
23
 
22
24
  __all__ = ["Result", "Simulator"]
23
25
 
@@ -362,31 +364,24 @@ class Simulator:
362
364
  self._initialise_integrator()
363
365
 
364
366
  def _initialise_integrator(self) -> None:
365
- from sympy import lambdify
366
-
367
- from mxlpy.symbolic import to_symbolic_model
368
-
369
- _jacobian = None
367
+ jac_fn = None
370
368
  if self.use_jacobian:
371
369
  try:
372
- # NOTE: this implementation is not correct in the sense
373
- # that it does not take parameter updates into account
374
- # jac = (
375
- # to_symbolic_model(self.model)
376
- # .jacobian()
377
- # .subs(self.model._parameters)
378
- # )
379
- # _jacobian = lambdify(
380
- # ("time", self.model.get_variable_names()),
381
- # jac,
382
- # )
383
-
384
- # NOTE: this implementation is correct, but slow as hell
385
- jac = to_symbolic_model(self.model).jacobian()
386
- _jacobian = lambda t, y: lambdify( # noqa: E731
387
- ("time", self.model.get_variable_names()),
388
- jac.subs(self.model._parameters), # noqa: SLF001
389
- )(t, y)
370
+ _jac = to_symbolic_model(self.model).jacobian()
371
+ _jac_fn = lambdify(
372
+ (
373
+ "time",
374
+ self.model.get_variable_names(),
375
+ self.model.get_parameter_names(),
376
+ ),
377
+ _jac,
378
+ )
379
+ jac_fn = lambda t, x: _jac_fn( # noqa: E731
380
+ t,
381
+ x,
382
+ self.model._parameters.values(), # noqa: SLF001
383
+ )
384
+
390
385
  except Exception as e: # noqa: BLE001
391
386
  warnings.warn(str(e), stacklevel=2)
392
387
 
@@ -394,7 +389,7 @@ class Simulator:
394
389
  self.integrator = self._integrator_type(
395
390
  self.model,
396
391
  [y0[k] for k in self.model.get_variable_names()],
397
- _jacobian,
392
+ jac_fn,
398
393
  )
399
394
 
400
395
  def clear_results(self) -> None:
mxlpy/types.py CHANGED
@@ -158,7 +158,6 @@ type IntegratorType = Callable[
158
158
  class Derived:
159
159
  """Container for a derived value."""
160
160
 
161
- name: str
162
161
  fn: RateFn
163
162
  args: list[str]
164
163
 
@@ -174,36 +173,35 @@ class Derived:
174
173
  """
175
174
  return cast(float, self.fn(*(dependent[arg] for arg in self.args)))
176
175
 
177
- def calculate_inpl(self, dependent: dict[str, float]) -> None:
176
+ def calculate_inpl(self, name: str, dependent: dict[str, float]) -> None:
178
177
  """Calculate the derived value in place.
179
178
 
180
179
  Args:
180
+ name: Name of the derived variable.
181
181
  dependent: Dictionary of dependent variables.
182
182
 
183
183
  """
184
- dependent[self.name] = cast(
185
- float, self.fn(*(dependent[arg] for arg in self.args))
186
- )
184
+ dependent[name] = cast(float, self.fn(*(dependent[arg] for arg in self.args)))
187
185
 
188
- def calculate_inpl_time_course(self, dependent: pd.DataFrame) -> None:
186
+ def calculate_inpl_time_course(self, name: str, dependent: pd.DataFrame) -> None:
189
187
  """Calculate the derived value in place.
190
188
 
191
189
  Args:
190
+ name: Name of the derived variable.
192
191
  dependent: Dictionary of dependent variables.
193
192
 
194
193
  """
195
194
  try:
196
- dependent[self.name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
195
+ dependent[name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
197
196
  except ValueError: # e.g. numpy.where
198
197
  sub = dependent.loc[:, self.args].to_numpy()
199
- dependent[self.name] = [self.fn(*row) for row in sub]
198
+ dependent[name] = [self.fn(*row) for row in sub]
200
199
 
201
200
 
202
201
  @dataclass(kw_only=True, slots=True)
203
202
  class Readout:
204
203
  """Container for a readout."""
205
204
 
206
- name: str
207
205
  fn: RateFn
208
206
  args: list[str]
209
207
 
@@ -219,36 +217,35 @@ class Readout:
219
217
  """
220
218
  return cast(float, self.fn(*(dependent[arg] for arg in self.args)))
221
219
 
222
- def calculate_inpl(self, dependent: dict[str, float]) -> None:
220
+ def calculate_inpl(self, name: str, dependent: dict[str, float]) -> None:
223
221
  """Calculate the readout in place.
224
222
 
225
223
  Args:
224
+ name: Name of the derived variable.
226
225
  dependent: Dictionary of dependent variables.
227
226
 
228
227
  """
229
- dependent[self.name] = cast(
230
- float, self.fn(*(dependent[arg] for arg in self.args))
231
- )
228
+ dependent[name] = cast(float, self.fn(*(dependent[arg] for arg in self.args)))
232
229
 
233
- def calculate_inpl_time_course(self, dependent: pd.DataFrame) -> None:
230
+ def calculate_inpl_time_course(self, name: str, dependent: pd.DataFrame) -> None:
234
231
  """Calculate the derived value in place.
235
232
 
236
233
  Args:
234
+ name: Name of the derived variable.
237
235
  dependent: Dictionary of dependent variables.
238
236
 
239
237
  """
240
238
  try:
241
- dependent[self.name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
239
+ dependent[name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
242
240
  except ValueError: # e.g. numpy.where
243
241
  sub = dependent.loc[:, self.args].to_numpy()
244
- dependent[self.name] = [self.fn(*row) for row in sub]
242
+ dependent[name] = [self.fn(*row) for row in sub]
245
243
 
246
244
 
247
245
  @dataclass(kw_only=True, slots=True)
248
246
  class Reaction:
249
247
  """Container for a reaction."""
250
248
 
251
- name: str
252
249
  fn: RateFn
253
250
  stoichiometry: Mapping[str, float | Derived]
254
251
  args: list[str]
@@ -272,29 +269,29 @@ class Reaction:
272
269
  """
273
270
  return cast(float, self.fn(*(dependent[arg] for arg in self.args)))
274
271
 
275
- def calculate_inpl(self, dependent: dict[str, float]) -> None:
272
+ def calculate_inpl(self, name: str, dependent: dict[str, float]) -> None:
276
273
  """Calculate the reaction in place.
277
274
 
278
275
  Args:
276
+ name: Name of the derived variable.
279
277
  dependent: Dictionary of dependent variables.
280
278
 
281
279
  """
282
- dependent[self.name] = cast(
283
- float, self.fn(*(dependent[arg] for arg in self.args))
284
- )
280
+ dependent[name] = cast(float, self.fn(*(dependent[arg] for arg in self.args)))
285
281
 
286
- def calculate_inpl_time_course(self, dependent: pd.DataFrame) -> None:
282
+ def calculate_inpl_time_course(self, name: str, dependent: pd.DataFrame) -> None:
287
283
  """Calculate the derived value in place.
288
284
 
289
285
  Args:
286
+ name: Name of the derived variable.
290
287
  dependent: Dictionary of dependent variables.
291
288
 
292
289
  """
293
290
  try:
294
- dependent[self.name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
291
+ dependent[name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
295
292
  except ValueError: # e.g. numpy.where
296
293
  sub = dependent.loc[:, self.args].to_numpy()
297
- dependent[self.name] = [self.fn(*row) for row in sub]
294
+ dependent[name] = [self.fn(*row) for row in sub]
298
295
 
299
296
 
300
297
  @dataclass(kw_only=True, slots=True)
@@ -464,11 +461,19 @@ class AbstractSurrogate:
464
461
  )
465
462
  )
466
463
 
467
- def calculate_inpl(self, args: dict[str, float]) -> None:
464
+ def calculate_inpl(
465
+ self,
466
+ name: str, # noqa: ARG002, for API compatibility
467
+ args: dict[str, float],
468
+ ) -> None:
468
469
  """Predict outputs based on input data."""
469
470
  args |= self.predict(np.array([args[arg] for arg in self.args]))
470
471
 
471
- def calculate_inpl_time_course(self, args: pd.DataFrame) -> None:
472
+ def calculate_inpl_time_course(
473
+ self,
474
+ name: str, # noqa: ARG002, for API compatibility
475
+ args: pd.DataFrame,
476
+ ) -> None:
472
477
  """Predict outputs based on input data."""
473
478
  args[list(self.stoichiometries)] = pd.DataFrame(
474
479
  [self.predict(y) for y in args.loc[:, self.args].to_numpy()],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mxlpy
3
- Version: 0.14.0
3
+ Version: 0.15.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>
@@ -4,10 +4,10 @@ mxlpy/fit.py,sha256=LwSoLfNVrqSlTtuUApwH36LjzGU0HLs4C_2qqTTjXFE,7859
4
4
  mxlpy/fns.py,sha256=ct_RFj9koW8vXHyr27GnbZUHUS_zfs4rDysybuFiOaU,4599
5
5
  mxlpy/identify.py,sha256=af52SCG4nlY9sSw22goaIheuvXR09QYK4ksCT24QHWI,1946
6
6
  mxlpy/label_map.py,sha256=urv-QTb0MUEKjwWvKtJSB8H2kvhLn1EKfRIH7awQQ8Y,17769
7
- mxlpy/linear_label_map.py,sha256=2lgERcUVDLXruRI08HBYJo_wK654y46voLUeBTzBy3k,10312
7
+ mxlpy/linear_label_map.py,sha256=DqzN_akacPccZwzYAR3ANIdzAU_GU6Xe6gWV9DHAAWU,10282
8
8
  mxlpy/mc.py,sha256=HWuJq4fV_wfTDERbLJRSF3fjCCYMxzLdqAyO53Z_uF8,16985
9
9
  mxlpy/mca.py,sha256=H0dfV45Kz5nMIW8s2V61op7x6LmI21wWgRf94i6iIY4,9328
10
- mxlpy/model.py,sha256=-BmS4bGCq_fMUnRLZG5uwl86ip_SiaWxsbgLPeV0nHQ,57656
10
+ mxlpy/model.py,sha256=qzol8nDSbM3HdESh50c4UFjn6Pw5JwcvhQ5AyKnbyvc,57576
11
11
  mxlpy/npe.py,sha256=oiRLA43-qf-AcS2KpQfJIOt7-Ev9Aj5sF6TMq9bJn84,8747
12
12
  mxlpy/parallel.py,sha256=kX4Td5YoovDwZp6kX_3cfO6QtHSS9ieJ0bMZiKs3Xv8,5002
13
13
  mxlpy/parameterise.py,sha256=2jMhhO-bHTFP_0kXercJekeATAZYBg5FrK1MQ_mWGpk,654
@@ -16,16 +16,16 @@ mxlpy/plot.py,sha256=4uu-6d8LH-GWX-sG_TlSpkSsnikv1DLTtnjJzA7nuRA,24670
16
16
  mxlpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  mxlpy/report.py,sha256=h7dhcBzPFydLPxdsEXokzDf7Ce4PirXMsvLqlDZLSWM,7181
18
18
  mxlpy/scan.py,sha256=-1SLyXJOX3U3CxeP1dEC4ytAoBMCH0Ql89wGvsG3LbI,18858
19
- mxlpy/simulator.py,sha256=vuTLuVanCIGAEqW8NUdGQvVKgoyvd45O-xBsbUoKaCI,21372
20
- mxlpy/types.py,sha256=RRhi1s6T9Yy8uZdLkWi7pvQTLmyPOlCgGTF8URYQGVA,14149
19
+ mxlpy/simulator.py,sha256=9Ne4P5Jrwgx4oAlljPvCqSCCy98_5Lv1B87y1AkbI4c,21041
20
+ mxlpy/types.py,sha256=AGWFK59MRRVBOr8I1EmFKGdRpF1DiT8C4lB95-oBk40,14512
21
21
  mxlpy/experimental/__init__.py,sha256=kZTE-92OErpHzNRqmgSQYH4CGXrogGJ5EL35XGZQ81M,206
22
22
  mxlpy/experimental/diff.py,sha256=4bztagJzFMsQJM7dlun_kv-WrWssM8CIw7gcL63hFf8,8952
23
23
  mxlpy/integrators/__init__.py,sha256=kqmV6a0TRyLGR_XqbyAI652AfptYnXAUpqbSFg0CpP8,450
24
24
  mxlpy/integrators/int_assimulo.py,sha256=d-4HHOj4vmGpg8ig2IXMO5CPiIrq89_quEKvCxIKrhw,4747
25
25
  mxlpy/integrators/int_scipy.py,sha256=dFHlYTeb2zX97f3VuNdMJdI7WEYshF4JAIgprKKk2z4,4581
26
26
  mxlpy/meta/__init__.py,sha256=Jyy4063fZy6iT4LSwjPyEAVr4N_3xxcLc8wDBoDPyKc,278
27
- mxlpy/meta/codegen_latex.py,sha256=1z0waYPmohY9GTJ_5DBuwXOXGTCHCH8E14tg6MYsf2A,13460
28
- mxlpy/meta/codegen_modebase.py,sha256=qQ8p6_KqMYCw7SRmf2HHRGvl25sYPKVI_zWKhzFhFLw,3138
27
+ mxlpy/meta/codegen_latex.py,sha256=R0OJqzE7PnOCWLk52C3XWuRb-zI2eYTvV2oJZJvPsOE,13414
28
+ mxlpy/meta/codegen_modebase.py,sha256=_ZAW4NvXhKwJQLGz5hkwwZpL2JMAJlfG-GUWkYIiNvw,3124
29
29
  mxlpy/meta/codegen_py.py,sha256=xSdeuEGPGc-QKRMgJO4VSPGMlxCPEV5prkKjNQ2D2hg,3483
30
30
  mxlpy/meta/source_tools.py,sha256=EN3OoGQaXeIsDTJvA7S15-xDBra3DCIyFZEJ6h0Fy0k,11125
31
31
  mxlpy/nn/__init__.py,sha256=yUc4o-iqfVVzkq9tZCstWwizrCqNlMft0YUwWGFFO-E,219
@@ -44,7 +44,7 @@ mxlpy/surrogates/_torch.py,sha256=E_1eDUlPSVFwROkdMDCqYwwHE-61pjNMJWotnhjzge0,58
44
44
  mxlpy/symbolic/__init__.py,sha256=3hQjCMw8-6iOxeUdfnCg8449fF_BRF2u6lCM1GPpkRY,222
45
45
  mxlpy/symbolic/strikepy.py,sha256=r6nRtckV1nxKq3i1bYYWZOkzwZ5XeKQuZM5ck44vUo0,20010
46
46
  mxlpy/symbolic/symbolic_model.py,sha256=YL9noEeP3_0DoKXwMPELtfmPuP6mgNcLIJgDRCkyB7A,2434
47
- mxlpy-0.14.0.dist-info/METADATA,sha256=WyKwohN13eTY0JZRyWaNpVFJfAD4z0gviWZ212aAKbo,4564
48
- mxlpy-0.14.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
49
- mxlpy-0.14.0.dist-info/licenses/LICENSE,sha256=bEzjyjy1stQhfRDVaVHa3xV1x-V8emwdlbMvYO8Zo84,35073
50
- mxlpy-0.14.0.dist-info/RECORD,,
47
+ mxlpy-0.15.0.dist-info/METADATA,sha256=EXj4l7bToJEQx3jbL26ECI_VuxtSgutyL44zdxLQ4Bg,4564
48
+ mxlpy-0.15.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
49
+ mxlpy-0.15.0.dist-info/licenses/LICENSE,sha256=bEzjyjy1stQhfRDVaVHa3xV1x-V8emwdlbMvYO8Zo84,35073
50
+ mxlpy-0.15.0.dist-info/RECORD,,
File without changes