mxlpy 0.12.0__py3-none-any.whl → 0.14.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/plot.py +14 -9
- mxlpy/simulator.py +29 -10
- mxlpy/types.py +10 -2
- {mxlpy-0.12.0.dist-info → mxlpy-0.14.0.dist-info}/METADATA +1 -1
- {mxlpy-0.12.0.dist-info → mxlpy-0.14.0.dist-info}/RECORD +7 -7
- {mxlpy-0.12.0.dist-info → mxlpy-0.14.0.dist-info}/WHEEL +0 -0
- {mxlpy-0.12.0.dist-info → mxlpy-0.14.0.dist-info}/licenses/LICENSE +0 -0
mxlpy/plot.py
CHANGED
@@ -52,7 +52,7 @@ __all__ = [
|
|
52
52
|
|
53
53
|
import itertools as it
|
54
54
|
import math
|
55
|
-
from typing import TYPE_CHECKING, Literal, cast
|
55
|
+
from typing import TYPE_CHECKING, Any, Literal, cast
|
56
56
|
|
57
57
|
import numpy as np
|
58
58
|
import pandas as pd
|
@@ -292,15 +292,19 @@ def reset_prop_cycle(ax: Axes) -> None:
|
|
292
292
|
def context(
|
293
293
|
colors: list[str] | None = None,
|
294
294
|
line_width: float | None = None,
|
295
|
+
line_style: Linestyle | None = None,
|
296
|
+
rc: dict[str, Any] | None = None,
|
295
297
|
) -> Generator[None, None, None]:
|
296
298
|
"""Context manager to set the defaults for plots.
|
297
299
|
|
298
300
|
Args:
|
299
301
|
colors: colors to use for the plot.
|
300
302
|
line_width: line width to use for the plot.
|
303
|
+
line_style: line style to use for the plot.
|
304
|
+
rc: additional keyword arguments to pass to the rc context.
|
301
305
|
|
302
306
|
"""
|
303
|
-
rc = {}
|
307
|
+
rc = {} if rc is None else rc
|
304
308
|
|
305
309
|
if colors is not None:
|
306
310
|
rc["axes.prop_cycle"] = cycler(color=colors)
|
@@ -308,6 +312,9 @@ def context(
|
|
308
312
|
if line_width is not None:
|
309
313
|
rc["lines.linewidth"] = line_width
|
310
314
|
|
315
|
+
if line_style is not None:
|
316
|
+
rc["lines.linestyle"] = line_style
|
317
|
+
|
311
318
|
with plt.rc_context(rc):
|
312
319
|
yield
|
313
320
|
|
@@ -476,19 +483,17 @@ def lines(
|
|
476
483
|
) -> FigAx:
|
477
484
|
"""Plot multiple lines on the same axis."""
|
478
485
|
fig, ax = _default_fig_ax(ax=ax, grid=grid)
|
479
|
-
ax.plot(
|
486
|
+
_lines = ax.plot(
|
480
487
|
x.index,
|
481
488
|
x,
|
482
|
-
# linestyle=linestyle,
|
483
|
-
# linewidth=linewidth,
|
484
489
|
alpha=alpha,
|
485
490
|
)
|
486
491
|
_default_labels(ax, xlabel=x.index.name, ylabel=None)
|
487
492
|
if legend:
|
488
|
-
if isinstance(x, pd.
|
489
|
-
|
490
|
-
|
491
|
-
|
493
|
+
names = x.columns if isinstance(x, pd.DataFrame) else [str(x.name)]
|
494
|
+
for line, name in zip(_lines, names, strict=True):
|
495
|
+
line.set_label(name)
|
496
|
+
ax.legend()
|
492
497
|
return fig, ax
|
493
498
|
|
494
499
|
|
mxlpy/simulator.py
CHANGED
@@ -10,6 +10,7 @@ Classes:
|
|
10
10
|
|
11
11
|
from __future__ import annotations
|
12
12
|
|
13
|
+
import warnings
|
13
14
|
from dataclasses import dataclass, field
|
14
15
|
from typing import TYPE_CHECKING, Literal, Self, cast, overload
|
15
16
|
|
@@ -319,6 +320,7 @@ class Simulator:
|
|
319
320
|
variables: list[pd.DataFrame] | None
|
320
321
|
dependent: list[pd.DataFrame] | None
|
321
322
|
simulation_parameters: list[dict[str, float]] | None
|
323
|
+
use_jacobian: bool
|
322
324
|
|
323
325
|
# For resets (e.g. update variable)
|
324
326
|
_integrator_type: IntegratorType
|
@@ -330,6 +332,7 @@ class Simulator:
|
|
330
332
|
y0: dict[str, float] | None = None,
|
331
333
|
integrator: IntegratorType = DefaultIntegrator,
|
332
334
|
*,
|
335
|
+
use_jacobian: bool = False,
|
333
336
|
test_run: bool = True,
|
334
337
|
) -> None:
|
335
338
|
"""Initialize the Simulator.
|
@@ -339,6 +342,7 @@ class Simulator:
|
|
339
342
|
y0: Initial conditions for the model variables.
|
340
343
|
If None, the initial conditions are obtained from the model.
|
341
344
|
integrator: The integrator to use for the simulation.
|
345
|
+
use_jacobian: Whether to use the Jacobian for the simulation.
|
342
346
|
test_run (bool, optional): If True, performs a test run for better error messages
|
343
347
|
|
344
348
|
"""
|
@@ -348,7 +352,9 @@ class Simulator:
|
|
348
352
|
self._integrator_type = integrator
|
349
353
|
self._time_shift = None
|
350
354
|
self.variables = None
|
355
|
+
self.dependent = None
|
351
356
|
self.simulation_parameters = None
|
357
|
+
self.use_jacobian = use_jacobian
|
352
358
|
|
353
359
|
if test_run:
|
354
360
|
self.model.get_right_hand_side(self.y0, time=0)
|
@@ -360,16 +366,29 @@ class Simulator:
|
|
360
366
|
|
361
367
|
from mxlpy.symbolic import to_symbolic_model
|
362
368
|
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
369
|
+
_jacobian = None
|
370
|
+
if self.use_jacobian:
|
371
|
+
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)
|
390
|
+
except Exception as e: # noqa: BLE001
|
391
|
+
warnings.warn(str(e), stacklevel=2)
|
373
392
|
|
374
393
|
y0 = self.y0
|
375
394
|
self.integrator = self._integrator_type(
|
mxlpy/types.py
CHANGED
@@ -192,7 +192,11 @@ class Derived:
|
|
192
192
|
dependent: Dictionary of dependent variables.
|
193
193
|
|
194
194
|
"""
|
195
|
-
|
195
|
+
try:
|
196
|
+
dependent[self.name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
|
197
|
+
except ValueError: # e.g. numpy.where
|
198
|
+
sub = dependent.loc[:, self.args].to_numpy()
|
199
|
+
dependent[self.name] = [self.fn(*row) for row in sub]
|
196
200
|
|
197
201
|
|
198
202
|
@dataclass(kw_only=True, slots=True)
|
@@ -233,7 +237,11 @@ class Readout:
|
|
233
237
|
dependent: Dictionary of dependent variables.
|
234
238
|
|
235
239
|
"""
|
236
|
-
|
240
|
+
try:
|
241
|
+
dependent[self.name] = self.fn(*dependent.loc[:, self.args].to_numpy().T)
|
242
|
+
except ValueError: # e.g. numpy.where
|
243
|
+
sub = dependent.loc[:, self.args].to_numpy()
|
244
|
+
dependent[self.name] = [self.fn(*row) for row in sub]
|
237
245
|
|
238
246
|
|
239
247
|
@dataclass(kw_only=True, slots=True)
|
@@ -12,12 +12,12 @@ 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
|
14
14
|
mxlpy/paths.py,sha256=TK2wO4N9lG-UV1JGfeB64q48JVDbwqIUj63rl55MKuQ,1022
|
15
|
-
mxlpy/plot.py,sha256=
|
15
|
+
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=
|
20
|
-
mxlpy/types.py,sha256=
|
19
|
+
mxlpy/simulator.py,sha256=vuTLuVanCIGAEqW8NUdGQvVKgoyvd45O-xBsbUoKaCI,21372
|
20
|
+
mxlpy/types.py,sha256=RRhi1s6T9Yy8uZdLkWi7pvQTLmyPOlCgGTF8URYQGVA,14149
|
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
|
@@ -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.
|
48
|
-
mxlpy-0.
|
49
|
-
mxlpy-0.
|
50
|
-
mxlpy-0.
|
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,,
|
File without changes
|
File without changes
|