Skip to main content

TSDynamics

Python CI Release Docs PyPI codecov

Dynamical systems in Python: 177 built-in systems, a native Rust integration engine, and a chaos-analysis toolkit — with the simplest system-definition contract anywhere.

You write the math (one symbolic method); TSDynamics lowers it to a native Rust engine and handles integration, Lyapunov spectra, bifurcation diagrams, Poincaré sections, attractors & basins — and even the documentation page for your system.

A spinning Lorenz attractor
A built-in Lorenz attractor — integrated, spun, and saved to a GIF (code below).

import tsdynamics as ts

lor = ts.systems.Lorenz(ic=[1.0, 1.0, 1.0])
traj = lor.run(final_time=100.0, dt=0.01)   # `run` is the one verb, every family
traj["x"]                                   # named component access

print(ts.analysis.lyapunov_spectrum(lor))   # an analysis is a free function
# LyapunovSpectrum  λ = [0.916, 0.0001893, -14.58]   chaotic · D_KY = 2.063   (Lorenz)

📖 Documentation: https://el3ssar.github.io/TSDynamics/


Define your own system

import tsdynamics as ts

class Rossler(ts.ContinuousSystem):
    variables = ("x", "y", "z")            # dim inferred = 3
    params = {"a": 0.2, "b": 0.2, "c": 5.7}
    _reference = "Rössler (1976), Phys. Lett. A 57, 397-398"

    def _equations(y, t, a, b, c):
        x, yv, z = y(0), y(1), y(2)
        return (-yv - z, x + a * yv, b + z * (x - c))

That's the whole contract. The class auto-registers: every analysis tool works on it, the test-suite sweeps it, and the docs build renders its equations (LaTeX, straight from the symbolics) and its attractor — zero extra steps. Delay systems use y(0, t - tau); maps implement _step (the Jacobian is derived from it); SDEs add a _diffusion term. Rossler().info prints everything the library read back to you.

From equations to figures

There is one plotting verb, and it has one rule: ts.plot draws everything you hand it on one figure and gives you back a Plot — a positional string says how to draw, everything else says what to draw, and a Plot handed back in is just another thing to draw. That last clause is why grids, movies and escape-to-matplotlib need no extra API. The Plot is backend-neutral: tweak it fluently, then save to matplotlib, plotly (interactive), three.js or JSON.

Bifurcation diagram of the logistic map, with the period-doubling onsets marked — orbit_diagram is one call, and .bifurcation_points() finds the cascade ($r_1 = 3$, $r_2 = 1 + \sqrt6 \approx 3.449$, …):

import numpy as np, tsdynamics as ts

orbit = ts.analysis.orbit_diagram(ts.systems.Logistic(), "r", np.linspace(2.8, 4.0, 2000))
pts = orbit.bifurcation_points()

p = ts.plot(orbit, color="k", markersize=0.2, alpha=0.5,   # tiny translucent dots
            xlabel="r", ylabel="x*", title="Logistic bifurcation")
for i, lbl in [(0, " r₁"), (1, " r₂"), (3, " r₄")]:        # mark the onsets
    p.vline(pts[i], label=lbl, color="red", linestyle="dashed")
p.save("bifurcation.png", size=(1600, 700))

Logistic bifurcation diagram

A PDE, too — the Kuramoto–Sivashinsky equation is a built-in spatially extended system; its space–time field is auto-detected and drawn as a heatmap:

import tsdynamics as ts

ks = ts.systems.KuramotoSivashinsky(N=128, L=22.0)
traj = ks.run(final_time=200.0, dt=0.25)
ts.plot(traj).save("ks.png")              # 128-mode space–time field

Kuramoto–Sivashinsky space–time field

Named plots, grids, primitives. Beyond the auto-detected default, a positional string names a plot transform — 38 of them, from nullclines and streamlines to ftle, cobweb, invariant_density and trace_determinant. Each declares which primitives can draw it, so you pick the drawing without touching a backend; and because a Plot is itself a legal subject, a grid of different plots is the same call:

import numpy as np, tsdynamics as ts

vdp = ts.systems.VanDerPol(params={"mu": 1.0})
traj = vdp.run(final_time=30.0, dt=0.01, ic=[0.5, 0.0])

ts.plot(vdp, traj, "flow_speed", "nullclines")                   # overlay, order-free
ts.plot(ts.plot(traj), ts.plot(traj, "psd"), layout="row")       # a grid
ts.viz.draw({"x": np.arange(5.0), "y": np.arange(5.0) ** 2}, "line")   # bare arrays

@ts.viz.transforms.register(source="data", frame="time", kind="diagnostic_curve",
                            primitives=("line", "points"))
def speed(traj):
    """Instantaneous speed |dx/dt| along the orbit."""
    return {"x": traj.t[1:],
            "y": np.linalg.norm(np.diff(traj.y, axis=0), axis=1) / np.diff(traj.t)}

ts.plot(traj, "speed")   # ...now in the gallery, the matrix, and every plot door

A transform owns no new math — it adapts an estimator from tsdynamics.analysis. The gallery is generated from the registry, so every picture there is produced by the snippet printed beside it.

The spinning attractor at the top is the same call, animated:

import tsdynamics as ts

traj = ts.systems.Lorenz().run(final_time=100.0, dt=0.01)
p = ts.plot(traj, animate=True)
p.style(axes=False).trail(None).camera(spin=0.4)      # full curve, no axes, rotate
p.animate(fps=30, duration=10, loop=True)
p.save("lorenz.gif")

A taste of the analysis layer

import numpy as np, tsdynamics as ts

# Poincaré section of the Rössler attractor (root-refined crossings)
section = ts.analysis.poincare_section(ts.systems.Rossler(), plane=("y", 0.0, "up"), crossings=500)

# Fixed points of the Hénon map, with stability — the repr IS the report
print(ts.analysis.fixed_points(ts.systems.Henon()))
# FixedPointSet  2 points · 0 stable, 2 unstable   (Henon)
#     [0] x* = [-1.1314 -0.3394]  unstable  |λ|max = 3.26
#     [1] x* = [0.6314 0.1894]  unstable  |λ|max = 1.924

# Maximal Lyapunov exponent — no Jacobian needed
ts.analysis.lyapunov_spectrum(ts.systems.Lorenz(), k=1, ic=[1, 1, 1])     # ≈ 0.90

Plus: attractors & basins of any flow or map, correlation/Rényi fractal dimensions, RQA (recurrence quantification), delay embedding (Takens, optimal τ, Cao/FNN), periodic orbits (shooting, Davidchack–Lai, rigorous interval enclosure), GALI, the 0–1 chaos test & Hunt–Ott expansion entropy, and Lyapunov exponents from a bare time series (Kantz/Rosenstein).

Highlights

  • Four families, one interface — ODEs, DDEs, SDEs and discrete maps all answer the same run verb and the same stepping protocol (reinit / step / state / time), so every analysis composes over all of them.

  • A small surface — tsdynamics.<TAB> is 17 names, lorenz.<TAB> is 19, and every analysis is a free function whose first argument is its subject (ts.analysis.lyapunov_spectrum(lorenz)). A name that moved raises an error printing its new address; that error is the migration guide.

  • 177 built-in systems with literature parameters (142 ODEs, 26 maps, 6 DDEs, 3 SDEs).

  • Native engine: equations lower to a Rust engine in-process and run on a built-in Cranelift JIT (or a bit-for-bit identical SSA-tape interpreter); parameters are runtime values, so changing them is free, and nothing is ever written to disk.

  • dt samples, rtol decides — the output grid and the accuracy knob are separate. The adaptive steppers use genuine dense output, so a coarse dt is cheap without being less accurate, and max_step= is there when you need to bound the step explicitly. Defaults are rtol=1e-9 / atol=1e-12.

  • Composition — a Poincaré section of a flow is a discrete map, so ts.analysis.orbit_diagram(ros.poincare("y", 0.0), "c", values) draws the bifurcation diagram of a flow in one line.

  • Backend-neutral plotting — one Plot renders to matplotlib, plotly (interactive + animated HTML), three.js, or JSON, with a fluent styling/theming vocabulary and registries for transforms, primitives, themes and renderers.

Install

pip install tsdynamics            # or: uv add tsdynamics

A prebuilt abi3 wheel (manylinux / musllinux / macOS / Windows) bundles the native Rust engine. No Rust toolchain and no C compiler needed to install or run. Optional plotting extra: tsdynamics[plot,interactive] (matplotlib, plotly).

Development

git clone https://github.com/El3ssar/TSDynamics && cd TSDynamics
uv sync --group dev --group docs
make test                                # change-scoped fast tier (the loop)
make test-slow                           # change-scoped slow tier
make test-all                            # whole fast tier — pre-push sanity
TSD_DOCS_FIGURES=0 uv run mkdocs serve   # docs preview

The suite is registry-driven — every test is parametrized over all 177 systems — so a plain pytest is thousands of items. make test runs only what your diff touches, which is what CI does too.

Releases are automated: conventional-commit PR titles drive semantic-release on merge. See CONTRIBUTING.

License

MIT © Daniel Estevez

Metadata

Release files for tsdynamics 6.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tsdynamics 6.0.0
File Size Uploaded
tsdynamics-6.0.0.tar.gz 1.6 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for tsdynamics 6.0.0
File
tsdynamics-6.0.0-cp312-abi3-win_amd64.whl CPython 3.12 abi3 Windows x86-64 Details
tsdynamics-6.0.0-cp312-abi3-musllinux_1_2_x86_64.whl CPython 3.12 abi3 Linux musl 1.2+ x86-64 Details
tsdynamics-6.0.0-cp312-abi3-musllinux_1_2_aarch64.whl CPython 3.12 abi3 Linux musl 1.2+ ARM64 Details
tsdynamics-6.0.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.12 abi3 Linux glibc 2.17+ x86-64 Details
tsdynamics-6.0.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.12 abi3 Linux glibc 2.17+ ARM64 Details
tsdynamics-6.0.0-cp312-abi3-macosx_11_0_arm64.whl CPython 3.12 abi3 macOS 11.0+ ARM64 Details
tsdynamics-6.0.0-cp312-abi3-macosx_10_12_x86_64.whl CPython 3.12 abi3 macOS 10.12+ x86-64 Details

Total release size: 25.2 MB

Release files / tsdynamics-6.0.0.tar.gz

Download URL tsdynamics-6.0.0.tar.gz
Size 1.6 MB
Tags Source
SHA-256 checksum
How to use checksums
2016281a3f8fa7dd7a25f48abfd12097e4bd7ad571530068aa31ab133d3452e7
BLAKE2b-256 checksum
How to use checksums
238b81f41817204ae2773d9fcc9c11e5bd1b16015470b3b5507ada037a6ac98d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / tsdynamics-6.0.0-cp312-abi3-win_amd64.whl

Download URL tsdynamics-6.0.0-cp312-abi3-win_amd64.whl
Size 3.5 MB
Tags CPython 3.12 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
8d54cf1ae33971e8a9f9f4da0467b3e36c9696882b6803f65c2fc285104262d3
BLAKE2b-256 checksum
How to use checksums
4f6ee9a87b091018f0f1bbc0a426d3ea83b69d66822f18c0ed7c553eb0f04f1f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / tsdynamics-6.0.0-cp312-abi3-musllinux_1_2_x86_64.whl

Download URL tsdynamics-6.0.0-cp312-abi3-musllinux_1_2_x86_64.whl
Size 3.8 MB
Tags CPython 3.12 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
85a7efd042c2f01a85ae0a4731c9fd064f817427ca8b54821ae967732d450e9e
BLAKE2b-256 checksum
How to use checksums
d2af5274598ae5527ff83e17ac08a9e987e1593fcc673825bc70009b50e0dbd1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / tsdynamics-6.0.0-cp312-abi3-musllinux_1_2_aarch64.whl

Download URL tsdynamics-6.0.0-cp312-abi3-musllinux_1_2_aarch64.whl
Size 3.2 MB
Tags CPython 3.12 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
d1bf69975df20f2340a4c0c8f67b298469361aa0c596b6201192e7db987179c3
BLAKE2b-256 checksum
How to use checksums
db454bdd03c22728f5ede0afa6bb4dd8031ecc098fe8f8a10504c8d2a8dee32a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / tsdynamics-6.0.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL tsdynamics-6.0.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.6 MB
Tags CPython 3.12 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
f249603ceda984e347dbd4bdfa6115f2d0af0e3b2189452a3e3d557f909dceb0
BLAKE2b-256 checksum
How to use checksums
31f3a8493a9bd75609c7e6f9e3013ca818e598c7bfbea214afd96edc52dadabf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / tsdynamics-6.0.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL tsdynamics-6.0.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 3.0 MB
Tags CPython 3.12 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
1e601c7dd907ec16a487f741a2e12a0b981420af56b2de51e627ca952011edd8
BLAKE2b-256 checksum
How to use checksums
6dc788315844e9f83dc73513afdc50dba47a5b6e6c8715af8188be4b694dd2ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / tsdynamics-6.0.0-cp312-abi3-macosx_11_0_arm64.whl

Download URL tsdynamics-6.0.0-cp312-abi3-macosx_11_0_arm64.whl
Size 2.9 MB
Tags CPython 3.12 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
de7bd997f9a88f2be5a37a826c4b1a60ecadbbadcd0faef9aac6bd53ae4c331e
BLAKE2b-256 checksum
How to use checksums
1c91624de934a1f491bd3ca22e2c5ca3c925558d778a61fa928870c92d1b5a03
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / tsdynamics-6.0.0-cp312-abi3-macosx_10_12_x86_64.whl

Download URL tsdynamics-6.0.0-cp312-abi3-macosx_10_12_x86_64.whl
Size 3.5 MB
Tags CPython 3.12 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
ee7b919b3cf478bde4bd98bb39dd3f1b207527f2fcac6367e0ad65ac2927e745
BLAKE2b-256 checksum
How to use checksums
fda15cdf429032ac25d351a68432834838d53ebcf5471cfbf55357dde4b436d8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release history Release notifications | RSS feed

6.0.1

8 release files

This release

6.0.0 This release

8 release files

5.4.0

8 release files

5.3.1

8 release files

5.3.0

8 release files

5.2.6

8 release files

5.2.5

8 release files

5.2.4

8 release files

5.2.3

8 release files

5.2.2

8 release files

5.2.1

8 release files

5.2.0

8 release files

5.1.0

8 release files

5.0.0

8 release files

4.3.1

8 release files

4.3.0

8 release files

4.2.0

8 release files

4.1.0

8 release files

4.0.1

8 release files

4.0.0

8 release files

3.2.1

8 release files

3.2.0

8 release files

3.1.4

8 release files

3.1.3

8 release files

3.1.2

8 release files

3.1.1

8 release files

3.1.0

8 release files

3.0.5

8 release files

3.0.4

8 release files

3.0.3

8 release files

3.0.2

8 release files

3.0.1

8 release files

3.0.0

8 release files

2.5.1

2 release files

2.5.0

2 release files

2.4.1

2 release files

2.4.0

2 release files

2.3.0

2 release files

2.2.2

2 release files

2.2.1

2 release files

2.2.0

2 release files

2.1.1

2 release files

2.1.0

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.0.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page