tsdynamics 3.0.1__tar.gz → 3.0.2__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.
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/PKG-INFO +1 -1
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-core/src/bridge.rs +133 -3
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-core/src/lib.rs +98 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/pyproject.toml +1 -1
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/__init__.py +1 -1
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/__init__.py +11 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/_result.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/basins/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/basins/_common.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/basins/attractors.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/basins/basins.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/basins/continuation.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/basins/metrics.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/chaos/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/chaos/expansion.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/chaos/gali.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/chaos/zero_one.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/dimensions/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/dimensions/_common.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/dimensions/_scaling.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/dimensions/correlation.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/dimensions/fixedmass.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/dimensions/generalized.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/embedding/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/embedding/_common.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/embedding/delay.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/embedding/dimension.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/embedding/embed.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/core.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/dispersion.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/lz.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/multiscale.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/permutation.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/sample.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/fixedpoints/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/fixedpoints/fixed.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/fixedpoints/periodic.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/lyapunov/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/lyapunov/from_data.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/orbits/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/orbits/orbit_diagram.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/orbits/poincare.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/orbits/return_map.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/recurrence/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/recurrence/_common.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/recurrence/matrix.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/recurrence/rqa.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/recurrence/windowed.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/surrogate/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/surrogate/_common.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/surrogate/generators.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/surrogate/hypothesis.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/surrogate/statistics.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/data/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/data/sampling.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/derived/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/derived/_base.py +5 -0
- tsdynamics-3.0.2/src/tsdynamics/derived/_crossings.py +194 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/derived/_variational.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/derived/ensemble.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/derived/poincare.py +85 -9
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/derived/projected.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/derived/stroboscopic.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/derived/tangent.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/derived/wrapped.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/engine/__init__.py +10 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/engine/compile.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/engine/problem.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/engine/run.py +121 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/errors.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/families/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/families/_accessors.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/families/_dde_lyapunov.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/families/base.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/families/delay.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/families/protocol.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/families/stochastic.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/plugins.py +24 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/registry.py +9 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/solvers/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/solvers/select.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/__init__.py +9 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/discrete/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/transforms/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/transforms/features.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/transforms/preprocessing.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/transforms/spectral.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/utils/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/utils/grids.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/utils/sagitta_dt.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/viz/__init__.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/viz/spec.py +5 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/LICENSE +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/README.md +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/Cargo.toml +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-core/Cargo.lock +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-core/Cargo.toml +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-engine/Cargo.toml +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/dde.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/ensemble.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/event.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/integrate.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/lib.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/map.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/problem.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/rng.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/sde.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/testkit.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/Cargo.toml +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/src/builder.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/src/eval.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/src/lib.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/src/op.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/src/reference.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/src/tape.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/coverage_tape.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/fixtures/CircadianRhythm.txt +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/fixtures/Lorenz.txt +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/fixtures/SanUmSrisuchinwong.txt +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/fixtures/SprottMore.txt +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/fixtures/Torus.txt +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/fixtures/YuWang2.txt +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/gen_fixtures.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/golden_fixtures.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/roundtrip.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-jit/Cargo.toml +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-jit/src/codegen.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-jit/src/error.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-jit/src/evaluator.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-jit/src/lib.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-jit/src/shims.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-jit/tests/compile_latency.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-jit/tests/golden_fixtures.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-jit/tests/interpreter_equivalence.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/Cargo.toml +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/caps.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/control.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/dop853.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/mod.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/rk4.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/rk45.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/testkit.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/tsit5.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/implicit/bdf.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/implicit/control.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/implicit/linalg.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/implicit/mod.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/implicit/rosenbrock.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/implicit/trbdf2.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/lib.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/registry.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/sde/euler_maruyama.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/sde/milstein.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/sde/mod.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/sde/testkit.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/solver.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/tests/explicit_accuracy.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/tests/implicit_stiff.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-solvers/tests/registry.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-vm/Cargo.toml +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-vm/src/interp.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-vm/src/lib.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-vm/tests/golden_fixtures.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/crates/tsdyn-vm/tests/oracle_equivalence.rs +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/chaos/_common.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/analysis/fixedpoints/_common.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/data/trajectory.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/engine/symbols.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/families/continuous.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/families/discrete.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/py.typed +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/solvers/explicit.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/solvers/implicit.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/solvers/stochastic.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/chaotic_attractors.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/chem_bio_systems.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/climate_geophysics.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/coupled_systems.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/delayed_systems.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/exotic_systems.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/oscillatory_systems.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/physical_systems.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/population_dynamics.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/discrete/chaotic_maps.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/discrete/exotic_maps.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/discrete/geometric_maps.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/discrete/polynomial_maps.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/systems/discrete/population_maps.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/transforms/_common.py +0 -0
- {tsdynamics-3.0.1 → tsdynamics-3.0.2}/src/tsdynamics/utils/general.py +0 -0
|
@@ -28,9 +28,10 @@
|
|
|
28
28
|
|
|
29
29
|
use tsdyn_engine::rng::SplitMix64;
|
|
30
30
|
use tsdyn_engine::{
|
|
31
|
-
ensemble_final as engine_ensemble, integrate_dde_grid,
|
|
32
|
-
iterate_ensemble_final as engine_iterate_ensemble,
|
|
33
|
-
|
|
31
|
+
ensemble_final as engine_ensemble, integrate_dde_grid, integrate_events, integrate_grid,
|
|
32
|
+
iterate_dense, iterate_ensemble_final as engine_iterate_ensemble,
|
|
33
|
+
sde_ensemble_final as engine_sde_ensemble, sde_integrate_grid, DelaySlot, EventDirection,
|
|
34
|
+
EventSpec, IntegrateConfig, IntegrateError, MapError, SdeConfig, SdeError,
|
|
34
35
|
};
|
|
35
36
|
use tsdyn_ir::{Evaluator, Tape};
|
|
36
37
|
use tsdyn_jit::JitEvaluator;
|
|
@@ -950,6 +951,135 @@ pub fn sde_ensemble_final(
|
|
|
950
951
|
Ok(result.states)
|
|
951
952
|
}
|
|
952
953
|
|
|
954
|
+
/// Map a Python-side direction code (`+1` / `-1` / `0`) to an [`EventDirection`].
|
|
955
|
+
fn event_direction(direction: i32) -> Result<EventDirection, EngineError> {
|
|
956
|
+
match direction {
|
|
957
|
+
1 => Ok(EventDirection::Rising),
|
|
958
|
+
-1 => Ok(EventDirection::Falling),
|
|
959
|
+
0 => Ok(EventDirection::Either),
|
|
960
|
+
other => Err(EngineError::BadShape(format!(
|
|
961
|
+
"event direction must be +1 (rising), -1 (falling) or 0 (either), got {other}"
|
|
962
|
+
))),
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/// Integrate `[t0, t1]` and return every crossing of the event function
|
|
967
|
+
/// `g(u, t) = 0` in `direction`, refined with the engine's O(h⁴) cubic-Hermite
|
|
968
|
+
/// dense output (stream WS-CROSSKERNEL — wiring the previously dead
|
|
969
|
+
/// [`tsdyn_engine::integrate_events`]).
|
|
970
|
+
///
|
|
971
|
+
/// `rhs` is the system right-hand side; `g` a single-output tape evaluated over
|
|
972
|
+
/// the full state (`g.dim() == 1`, `g.n_param() <= rhs.n_param()`). `first_step`
|
|
973
|
+
/// seeds the solver; with the fixed-step `rk4` it *is* the march step, so a caller
|
|
974
|
+
/// that wants the Python `PoincareMap`'s dt-grid detection (no skipped crossings,
|
|
975
|
+
/// answer-identical refinement) passes `method = "rk4"`, `first_step = dt`.
|
|
976
|
+
///
|
|
977
|
+
/// Returns `(times, states_flat, t_final, u_final, terminated)` — the `K` crossing
|
|
978
|
+
/// times, the row-major `(K, dim)` crossing states, the time/state the run stopped
|
|
979
|
+
/// at (so a caller can resume the next span exactly), and whether a terminal event
|
|
980
|
+
/// stopped it. Divergence raises ([`EngineError::Diverged`]), preserving the
|
|
981
|
+
/// "diverge loudly" contract of the per-`dt` Python path.
|
|
982
|
+
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
|
983
|
+
pub fn integrate_events_dense(
|
|
984
|
+
rhs: Tape,
|
|
985
|
+
g: Tape,
|
|
986
|
+
ic: &[f64],
|
|
987
|
+
p: &[f64],
|
|
988
|
+
t0: f64,
|
|
989
|
+
t1: f64,
|
|
990
|
+
first_step: f64,
|
|
991
|
+
direction: i32,
|
|
992
|
+
terminal: bool,
|
|
993
|
+
method: &str,
|
|
994
|
+
rtol: f64,
|
|
995
|
+
atol: f64,
|
|
996
|
+
jit: bool,
|
|
997
|
+
) -> Result<(Vec<f64>, Vec<f64>, f64, Vec<f64>, bool), EngineError> {
|
|
998
|
+
guard_continuous(&rhs)?;
|
|
999
|
+
check_inputs(&rhs, ic, p)?;
|
|
1000
|
+
if let Some(&bad) = ic.iter().find(|x| !x.is_finite()) {
|
|
1001
|
+
return Err(EngineError::BadShape(format!(
|
|
1002
|
+
"initial state must be finite, found {bad}"
|
|
1003
|
+
)));
|
|
1004
|
+
}
|
|
1005
|
+
let dim = rhs.dim();
|
|
1006
|
+
if dim == 0 {
|
|
1007
|
+
return Err(EngineError::BadShape(
|
|
1008
|
+
"system dimension is zero (the tape has no outputs)".to_string(),
|
|
1009
|
+
));
|
|
1010
|
+
}
|
|
1011
|
+
// The event function is a single-output tape over the full state; it shares
|
|
1012
|
+
// the system parameter vector (it may declare fewer and read the leading
|
|
1013
|
+
// slice). `eval_event` in the engine asserts both, so reject violations here
|
|
1014
|
+
// as a clean `ValueError` rather than a release-build panic.
|
|
1015
|
+
if g.dim() != 1 {
|
|
1016
|
+
return Err(EngineError::BadShape(format!(
|
|
1017
|
+
"event function must have a single output, got {}",
|
|
1018
|
+
g.dim()
|
|
1019
|
+
)));
|
|
1020
|
+
}
|
|
1021
|
+
if g.n_state() > dim {
|
|
1022
|
+
return Err(EngineError::BadShape(format!(
|
|
1023
|
+
"event function reads {} state inputs but the system has dim = {dim}",
|
|
1024
|
+
g.n_state()
|
|
1025
|
+
)));
|
|
1026
|
+
}
|
|
1027
|
+
if g.n_param() > p.len() {
|
|
1028
|
+
return Err(EngineError::BadShape(format!(
|
|
1029
|
+
"event function declares {} parameters but the system has {}",
|
|
1030
|
+
g.n_param(),
|
|
1031
|
+
p.len()
|
|
1032
|
+
)));
|
|
1033
|
+
}
|
|
1034
|
+
if !(t0.is_finite() && t1.is_finite()) {
|
|
1035
|
+
return Err(EngineError::BadShape(format!(
|
|
1036
|
+
"event integration span must be finite, got t0 = {t0}, t1 = {t1}"
|
|
1037
|
+
)));
|
|
1038
|
+
}
|
|
1039
|
+
if t1 < t0 {
|
|
1040
|
+
return Err(EngineError::BadShape(format!(
|
|
1041
|
+
"integrate_events is forward only: need t1 >= t0, got t0 = {t0}, t1 = {t1}"
|
|
1042
|
+
)));
|
|
1043
|
+
}
|
|
1044
|
+
// The engine asserts a finite, positive first step (a hard `assert!`, not a
|
|
1045
|
+
// debug one) — turn a bad value into a clean error at the boundary.
|
|
1046
|
+
if !(first_step.is_finite() && first_step > 0.0) {
|
|
1047
|
+
return Err(EngineError::BadShape(format!(
|
|
1048
|
+
"first step (the detection dt) must be finite and positive, got {first_step}"
|
|
1049
|
+
)));
|
|
1050
|
+
}
|
|
1051
|
+
let dir = event_direction(direction)?;
|
|
1052
|
+
let name = resolve_solver(method)?;
|
|
1053
|
+
require_jacobian_if_needed(&rhs, name)?;
|
|
1054
|
+
|
|
1055
|
+
let rhs_ev = build_evaluator(rhs, jit)?;
|
|
1056
|
+
let g_ev = build_evaluator(g, jit)?;
|
|
1057
|
+
let mut solver = build_solver(name, rtol, atol);
|
|
1058
|
+
let cfg = IntegrateConfig::new(first_step);
|
|
1059
|
+
|
|
1060
|
+
let spec = if terminal {
|
|
1061
|
+
EventSpec::terminal(&*g_ev, dir)
|
|
1062
|
+
} else {
|
|
1063
|
+
EventSpec::new(&*g_ev, dir)
|
|
1064
|
+
};
|
|
1065
|
+
let outcome = integrate_events(&*rhs_ev, &mut *solver, &ic[..dim], p, t0, t1, &[spec], &cfg)
|
|
1066
|
+
.map_err(|e| EngineError::Diverged(diverge_msg(&e)))?;
|
|
1067
|
+
|
|
1068
|
+
let mut times = Vec::with_capacity(outcome.hits.len());
|
|
1069
|
+
let mut states = Vec::with_capacity(outcome.hits.len() * dim);
|
|
1070
|
+
for hit in &outcome.hits {
|
|
1071
|
+
times.push(hit.t);
|
|
1072
|
+
states.extend_from_slice(&hit.u);
|
|
1073
|
+
}
|
|
1074
|
+
Ok((
|
|
1075
|
+
times,
|
|
1076
|
+
states,
|
|
1077
|
+
outcome.t_final,
|
|
1078
|
+
outcome.u_final,
|
|
1079
|
+
outcome.terminated,
|
|
1080
|
+
))
|
|
1081
|
+
}
|
|
1082
|
+
|
|
953
1083
|
/// Prefix the engine's diverge message so the Python `RuntimeError` reads clearly.
|
|
954
1084
|
fn diverge_msg(e: &IntegrateError) -> String {
|
|
955
1085
|
format!("integration diverged before reaching the final time: {e}")
|
|
@@ -591,6 +591,103 @@ fn integrate_sde_ensemble_final<'py>(
|
|
|
591
591
|
PyArray1::from_vec(py, flat).reshape([n_ic, dim])
|
|
592
592
|
}
|
|
593
593
|
|
|
594
|
+
// ---------------------------------------------------------------------------
|
|
595
|
+
// Event detection (two tapes: right-hand side + event function g)
|
|
596
|
+
// ---------------------------------------------------------------------------
|
|
597
|
+
|
|
598
|
+
/// Integrate `[t0, t1]` and return the crossings of the event function
|
|
599
|
+
/// `g(u, t) = 0` in `direction` (`+1` rising / `-1` falling / `0` either),
|
|
600
|
+
/// refined with the engine's O(h⁴) cubic-Hermite dense output.
|
|
601
|
+
///
|
|
602
|
+
/// The two tapes are passed back to back — first the right-hand side `f`, then the
|
|
603
|
+
/// single-output event function `g` (`g`'s `outputs.len() == 1`; it reads the full
|
|
604
|
+
/// state and may declare fewer parameters than the system, reading the leading
|
|
605
|
+
/// slice). `first_step` seeds the solver; with the fixed-step `rk4` it *is* the
|
|
606
|
+
/// detection step, so `method="rk4"`, `first_step=dt` reproduces the Python
|
|
607
|
+
/// `PoincareMap` dt-grid march and its refinement (answer-identical). `terminal`
|
|
608
|
+
/// stops the run at the first crossing. Divergence raises `RuntimeError`.
|
|
609
|
+
///
|
|
610
|
+
/// Returns `(times, states, t_final, u_final, terminated)`: the `(K,)` crossing
|
|
611
|
+
/// times, the `(K, dim)` crossing states, the time and state the run stopped at
|
|
612
|
+
/// (to resume the next span exactly), and whether a terminal event stopped it.
|
|
613
|
+
#[pyfunction]
|
|
614
|
+
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
|
615
|
+
fn integrate_events_dense<'py>(
|
|
616
|
+
py: Python<'py>,
|
|
617
|
+
ops: PyReadonlyArray1<i32>,
|
|
618
|
+
a: PyReadonlyArray1<i32>,
|
|
619
|
+
b: PyReadonlyArray1<i32>,
|
|
620
|
+
imm: PyReadonlyArray1<f64>,
|
|
621
|
+
outputs: PyReadonlyArray1<i32>,
|
|
622
|
+
jac_outputs: PyReadonlyArray1<i32>,
|
|
623
|
+
n_state: usize,
|
|
624
|
+
n_param: usize,
|
|
625
|
+
ops_g: PyReadonlyArray1<i32>,
|
|
626
|
+
a_g: PyReadonlyArray1<i32>,
|
|
627
|
+
b_g: PyReadonlyArray1<i32>,
|
|
628
|
+
imm_g: PyReadonlyArray1<f64>,
|
|
629
|
+
outputs_g: PyReadonlyArray1<i32>,
|
|
630
|
+
jac_outputs_g: PyReadonlyArray1<i32>,
|
|
631
|
+
n_state_g: usize,
|
|
632
|
+
n_param_g: usize,
|
|
633
|
+
ic: PyReadonlyArray1<f64>,
|
|
634
|
+
p: PyReadonlyArray1<f64>,
|
|
635
|
+
t0: f64,
|
|
636
|
+
t1: f64,
|
|
637
|
+
first_step: f64,
|
|
638
|
+
direction: i32,
|
|
639
|
+
terminal: bool,
|
|
640
|
+
method: String,
|
|
641
|
+
rtol: f64,
|
|
642
|
+
atol: f64,
|
|
643
|
+
jit: bool,
|
|
644
|
+
) -> PyResult<(
|
|
645
|
+
Bound<'py, PyArray1<f64>>,
|
|
646
|
+
Bound<'py, PyArray2<f64>>,
|
|
647
|
+
f64,
|
|
648
|
+
Bound<'py, PyArray1<f64>>,
|
|
649
|
+
bool,
|
|
650
|
+
)> {
|
|
651
|
+
let rhs = OwnedTape::copy_in(&ops, &a, &b, &imm, &outputs, &jac_outputs, n_state, n_param)?;
|
|
652
|
+
let g = OwnedTape::copy_in(
|
|
653
|
+
&ops_g,
|
|
654
|
+
&a_g,
|
|
655
|
+
&b_g,
|
|
656
|
+
&imm_g,
|
|
657
|
+
&outputs_g,
|
|
658
|
+
&jac_outputs_g,
|
|
659
|
+
n_state_g,
|
|
660
|
+
n_param_g,
|
|
661
|
+
)?;
|
|
662
|
+
let dim = rhs.dim();
|
|
663
|
+
let ic = vec_f64("ic", &ic)?;
|
|
664
|
+
let p = vec_f64("p", &p)?;
|
|
665
|
+
let (times, states, t_final, u_final, terminated) = py
|
|
666
|
+
.detach(|| {
|
|
667
|
+
bridge::integrate_events_dense(
|
|
668
|
+
rhs.build()?,
|
|
669
|
+
g.build()?,
|
|
670
|
+
&ic,
|
|
671
|
+
&p,
|
|
672
|
+
t0,
|
|
673
|
+
t1,
|
|
674
|
+
first_step,
|
|
675
|
+
direction,
|
|
676
|
+
terminal,
|
|
677
|
+
&method,
|
|
678
|
+
rtol,
|
|
679
|
+
atol,
|
|
680
|
+
jit,
|
|
681
|
+
)
|
|
682
|
+
})
|
|
683
|
+
.map_err(to_py_err)?;
|
|
684
|
+
let n_hits = times.len();
|
|
685
|
+
let times = PyArray1::from_vec(py, times);
|
|
686
|
+
let states = PyArray1::from_vec(py, states).reshape([n_hits, dim])?;
|
|
687
|
+
let u_final = PyArray1::from_vec(py, u_final);
|
|
688
|
+
Ok((times, states, t_final, u_final, terminated))
|
|
689
|
+
}
|
|
690
|
+
|
|
594
691
|
// ---------------------------------------------------------------------------
|
|
595
692
|
// Introspection
|
|
596
693
|
// ---------------------------------------------------------------------------
|
|
@@ -644,6 +741,7 @@ fn _rust(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
|
644
741
|
m.add_function(wrap_pyfunction!(integrate_ensemble_final, m)?)?;
|
|
645
742
|
m.add_function(wrap_pyfunction!(integrate_sde_dense, m)?)?;
|
|
646
743
|
m.add_function(wrap_pyfunction!(integrate_sde_ensemble_final, m)?)?;
|
|
744
|
+
m.add_function(wrap_pyfunction!(integrate_events_dense, m)?)?;
|
|
647
745
|
m.add_function(wrap_pyfunction!(solvers, m)?)?;
|
|
648
746
|
m.add_function(wrap_pyfunction!(_version, m)?)?;
|
|
649
747
|
Ok(())
|
|
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tsdynamics"
|
|
7
|
-
version = "3.0.
|
|
7
|
+
version = "3.0.2"
|
|
8
8
|
description = "Zero-warmup Rust-engine ODE/DDE/SDE integration, discrete maps, and chaos analysis for dynamical systems."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12,<4.0"
|
|
@@ -124,7 +124,7 @@ from .families import (
|
|
|
124
124
|
)
|
|
125
125
|
|
|
126
126
|
# Single source of truth for the package version; rewritten by python-semantic-release.
|
|
127
|
-
__version__ = "3.0.
|
|
127
|
+
__version__ = "3.0.2"
|
|
128
128
|
|
|
129
129
|
# Built-in system classes are NOT bound into this namespace — that would bury the
|
|
130
130
|
# submodules (``analysis``, ``data``, ``systems``, …) under ~149 model names in
|
|
@@ -177,6 +177,7 @@ __all__ = [
|
|
|
177
177
|
"correlation_dimension",
|
|
178
178
|
"correlation_sum",
|
|
179
179
|
"dimension_spectrum",
|
|
180
|
+
"discover_plugins",
|
|
180
181
|
"dispersion_entropy",
|
|
181
182
|
"embed",
|
|
182
183
|
"embedding_dimension",
|
|
@@ -250,3 +251,13 @@ def discover_plugins(*, strict: bool = False) -> list[str]:
|
|
|
250
251
|
# analyses register themselves from their own subpackages (the analysis streams);
|
|
251
252
|
# plugin failures are isolated inside `register_entry_points`.
|
|
252
253
|
discover_plugins()
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def __dir__() -> list[str]:
|
|
257
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete.
|
|
258
|
+
|
|
259
|
+
The capability subpackages (``basins``, ``chaos``, …) and plugin-wiring
|
|
260
|
+
helpers are re-exported flat or used internally; they stay importable but are
|
|
261
|
+
kept off the tab-completion surface so only the public quantifiers show.
|
|
262
|
+
"""
|
|
263
|
+
return sorted(__all__)
|
|
@@ -685,3 +685,8 @@ class ScalingResult(AnalysisResult):
|
|
|
685
685
|
layers=layers,
|
|
686
686
|
meta=dict(self.meta) if self.meta else {},
|
|
687
687
|
)
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
def __dir__() -> list[str]:
|
|
691
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
692
|
+
return sorted(__all__)
|
|
@@ -77,3 +77,8 @@ for _name, _fn, _needs in (
|
|
|
77
77
|
):
|
|
78
78
|
_registry.analyses.register(_name, _fn, needs=_needs, family="basins")
|
|
79
79
|
del _name, _fn, _needs
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def __dir__() -> list[str]:
|
|
83
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
84
|
+
return sorted(__all__)
|
|
@@ -173,3 +173,8 @@ def _apply_merge(labels: np.ndarray, merge: dict[int, int]) -> np.ndarray:
|
|
|
173
173
|
if old != new:
|
|
174
174
|
out[labels == old] = new
|
|
175
175
|
return out
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def __dir__() -> list[str]:
|
|
179
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
180
|
+
return sorted(__all__)
|
|
@@ -463,3 +463,8 @@ def resolve_merge_tol(cellgrid: _CellGrid, merge_tol: float | None) -> float:
|
|
|
463
463
|
def _looks_unsupported(system: Any) -> bool:
|
|
464
464
|
"""Return True for delay / stochastic systems (no finite-dimensional state)."""
|
|
465
465
|
return hasattr(system, "_drift") or hasattr(system, "history") or hasattr(system, "_delays")
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
def __dir__() -> list[str]:
|
|
469
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
470
|
+
return sorted(__all__)
|
|
@@ -353,3 +353,8 @@ def basin_fractions(
|
|
|
353
353
|
fractions = {k: c / n for k, c in merged_counts.items()}
|
|
354
354
|
attractors = mapper.attractor_set(diverged=diverged, seeds=n, merge=merge)
|
|
355
355
|
return BasinFractions(fractions=fractions, diverged=diverged / n, n=n, attractors=attractors)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def __dir__() -> list[str]:
|
|
359
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
360
|
+
return sorted(__all__)
|
|
@@ -270,3 +270,8 @@ def tipping_points(result: ContinuationResult, *, threshold: float = 0.0) -> lis
|
|
|
270
270
|
)
|
|
271
271
|
events.sort(key=lambda e: (e["value"], e["attractor"]))
|
|
272
272
|
return events
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def __dir__() -> list[str]:
|
|
276
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
277
|
+
return sorted(__all__)
|
|
@@ -471,3 +471,8 @@ def resilience(result: BasinsResult, attractor_id: int) -> float:
|
|
|
471
471
|
idx = np.rint((center - grid.lo) / spacing).astype(int)
|
|
472
472
|
idx = np.clip(idx, 0, np.asarray(grid.shape) - 1)
|
|
473
473
|
return float(edt[tuple(idx)])
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def __dir__() -> list[str]:
|
|
477
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
478
|
+
return sorted(__all__)
|
|
@@ -283,3 +283,8 @@ def _expansion_flow(
|
|
|
283
283
|
times[s] = s * dt
|
|
284
284
|
ln_e[s] = np.log(e) if e > 0.0 else -np.inf
|
|
285
285
|
return times, ln_e, int(np.count_nonzero(alive))
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def __dir__() -> list[str]:
|
|
289
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
290
|
+
return sorted(__all__)
|
|
@@ -300,3 +300,8 @@ class DimensionResult:
|
|
|
300
300
|
f"dimension={self.dimension:.4g} ± {self.stderr:.2g}, "
|
|
301
301
|
f"n_fit={self.fit_slice[1] - self.fit_slice[0] + 1})"
|
|
302
302
|
)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def __dir__() -> list[str]:
|
|
306
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
307
|
+
return sorted(__all__)
|
|
@@ -182,3 +182,8 @@ def local_slopes(x: np.ndarray, y: np.ndarray) -> np.ndarray:
|
|
|
182
182
|
if x.size < 2:
|
|
183
183
|
return np.full(x.shape, np.nan)
|
|
184
184
|
return np.gradient(y, x)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def __dir__() -> list[str]:
|
|
188
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
189
|
+
return sorted(__all__)
|
|
@@ -59,3 +59,8 @@ for _name, _fn in (
|
|
|
59
59
|
):
|
|
60
60
|
_registry.analyses.register(_name, _fn, needs="series", family="embedding")
|
|
61
61
|
del _name, _fn
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def __dir__() -> list[str]:
|
|
65
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
66
|
+
return sorted(__all__)
|
|
@@ -131,3 +131,8 @@ def _as_channels(x: Any) -> np.ndarray:
|
|
|
131
131
|
if not np.all(np.isfinite(arr)):
|
|
132
132
|
raise ValueError("channel data contains non-finite values (nan/inf).")
|
|
133
133
|
return arr
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def __dir__() -> list[str]:
|
|
137
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
138
|
+
return sorted(__all__)
|
|
@@ -227,3 +227,8 @@ def optimal_delay(
|
|
|
227
227
|
return max(int(acf.size) - 1, 1) # never crosses → longest lag available
|
|
228
228
|
|
|
229
229
|
raise ValueError(f"unknown method {method!r}; use 'mi', 'acf', or 'acf_zero'.")
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def __dir__() -> list[str]:
|
|
233
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
234
|
+
return sorted(__all__)
|
|
@@ -336,3 +336,8 @@ def embedding_dimension(
|
|
|
336
336
|
data, delay=delay, max_dim=max_dim, component=component, **kwargs
|
|
337
337
|
)
|
|
338
338
|
raise ValueError(f"unknown method {method!r}; use 'cao' or 'fnn'.")
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def __dir__() -> list[str]:
|
|
342
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
343
|
+
return sorted(__all__)
|
|
@@ -161,3 +161,8 @@ def _embed_single(series: np.ndarray, m: int, tau: int) -> np.ndarray:
|
|
|
161
161
|
start = j * tau
|
|
162
162
|
out[:, j] = series[start : start + rows]
|
|
163
163
|
return out
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def __dir__() -> list[str]:
|
|
167
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
168
|
+
return sorted(__all__)
|
|
@@ -91,3 +91,8 @@ for _name, _fn in {
|
|
|
91
91
|
"lz76_entropy": lz76_entropy,
|
|
92
92
|
}.items():
|
|
93
93
|
_registry.analyses.register(_name, _fn, needs="series")
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def __dir__() -> list[str]:
|
|
97
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
98
|
+
return sorted(__all__)
|
|
@@ -552,3 +552,8 @@ def entropy(
|
|
|
552
552
|
hmax = measure.maximum(outcomes.cardinality)
|
|
553
553
|
return h / hmax if hmax > 0 else 0.0
|
|
554
554
|
return h
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
def __dir__() -> list[str]:
|
|
558
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
559
|
+
return sorted(__all__)
|
|
@@ -297,3 +297,8 @@ def _lz76_via_lzcomplexity(codes: np.ndarray, k: int) -> int:
|
|
|
297
297
|
# list[int] → concatenated-decimals gotcha) and pass the resulting string.
|
|
298
298
|
text = "".join(chr(0x30 + int(code)) for code in codes)
|
|
299
299
|
return int(lz.lz76Factorization(text))
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def __dir__() -> list[str]:
|
|
303
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
304
|
+
return sorted(__all__)
|
|
@@ -122,3 +122,8 @@ def multiscale_entropy(
|
|
|
122
122
|
for k, s in enumerate(scale_list):
|
|
123
123
|
out[k] = entropy_fn(coarse_grain(series, s), **call_kwargs)
|
|
124
124
|
return out
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def __dir__() -> list[str]:
|
|
128
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
129
|
+
return sorted(__all__)
|
|
@@ -121,3 +121,8 @@ def weighted_permutation_entropy(
|
|
|
121
121
|
hmax = Shannon(base).maximum(space.cardinality)
|
|
122
122
|
return h / hmax if hmax > 0 else 0.0
|
|
123
123
|
return h
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def __dir__() -> list[str]:
|
|
127
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
128
|
+
return sorted(__all__)
|
|
@@ -242,3 +242,8 @@ def _stabilising_matrices(method: str, dim: int, max_c: int | None) -> list[np.n
|
|
|
242
242
|
stacklevel=3,
|
|
243
243
|
)
|
|
244
244
|
return mats
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def __dir__() -> list[str]:
|
|
248
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
249
|
+
return sorted(__all__)
|
|
@@ -600,3 +600,8 @@ def _fft_period_lag(y: np.ndarray) -> float:
|
|
|
600
600
|
if k == 0:
|
|
601
601
|
raise ValueError("estimate_period: no dominant frequency found.")
|
|
602
602
|
return float(n / k)
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
def __dir__() -> list[str]:
|
|
606
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
607
|
+
return sorted(__all__)
|
|
@@ -187,3 +187,8 @@ for _name, _fn, _meta in (
|
|
|
187
187
|
):
|
|
188
188
|
_registry.analyses.register(_name, _fn, **_meta)
|
|
189
189
|
del _name, _fn, _meta
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def __dir__() -> list[str]:
|
|
193
|
+
"""Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete."""
|
|
194
|
+
return sorted(__all__)
|