stochasticforceinference 2.0.3__tar.gz → 2.1.0__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.
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/AGENTS.md +73 -11
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/MANIFEST.in +1 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/PKG-INFO +103 -44
- stochasticforceinference-2.1.0/README.md +218 -0
- stochasticforceinference-2.1.0/SFI/AGENT_GUIDE.md +231 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/__init__.py +24 -4
- stochasticforceinference-2.1.0/SFI/__main__.py +70 -0
- stochasticforceinference-2.1.0/SFI/_version.py +36 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/bases/pairs.py +60 -13
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/diagnostics/__init__.py +10 -1
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/diagnostics/assess.py +21 -3
- stochasticforceinference-2.1.0/SFI/diagnostics/diffusion_check.py +63 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/diagnostics/dynamics_order.py +69 -71
- stochasticforceinference-2.1.0/SFI/diagnostics/finite_dt.py +190 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/diagnostics/plotting.py +22 -9
- stochasticforceinference-2.1.0/SFI/diagnostics/psd.py +93 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/diagnostics/report.py +116 -9
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/diagnostics/residual_tests.py +57 -18
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/diagnostics/residuals.py +326 -4
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/__init__.py +3 -1
- stochasticforceinference-2.1.0/SFI/inference/_oli_diffusion.py +667 -0
- stochasticforceinference-2.1.0/SFI/inference/_oli_instrument.py +1049 -0
- stochasticforceinference-2.1.0/SFI/inference/_uli_constant_noise.py +931 -0
- stochasticforceinference-2.1.0/SFI/inference/_uli_diffusion.py +348 -0
- stochasticforceinference-2.1.0/SFI/inference/_uli_drift_check.py +103 -0
- stochasticforceinference-2.1.0/SFI/inference/_uli_model_free.py +729 -0
- stochasticforceinference-2.1.0/SFI/inference/_uli_path_resolution.py +143 -0
- stochasticforceinference-2.1.0/SFI/inference/_uli_stride.py +258 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/base.py +856 -76
- stochasticforceinference-2.1.0/SFI/inference/graph_diffusion.py +523 -0
- stochasticforceinference-2.1.0/SFI/inference/overdamped.py +2268 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/parametric_core/driver.py +26 -4
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/parametric_core/flow_multi.py +143 -33
- stochasticforceinference-2.1.0/SFI/inference/parametric_core/frame_extras.py +112 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/parametric_core/precompute.py +58 -26
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/parametric_core/runner.py +367 -84
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/parametric_core/solve.py +165 -94
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/result.py +18 -5
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/sparse/__init__.py +20 -1
- stochasticforceinference-2.1.0/SFI/inference/sparse/exhaustive.py +107 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/sparse/hillclimb.py +9 -4
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/sparse/result.py +215 -9
- stochasticforceinference-2.1.0/SFI/inference/sparse/units.py +514 -0
- stochasticforceinference-2.1.0/SFI/inference/underdamped.py +3445 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/integrate/__init__.py +11 -1
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/integrate/api.py +559 -50
- stochasticforceinference-2.1.0/SFI/integrate/integrand.py +659 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/integrate/timeops.py +23 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/langevin/base.py +115 -8
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/langevin/chunked.py +2 -3
- stochasticforceinference-2.1.0/SFI/langevin/graph_noise.py +498 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/langevin/noise.py +9 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/langevin/overdamped.py +43 -23
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/langevin/underdamped.py +94 -56
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/factory.py +19 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/base.py +16 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/interactions/__init__.py +2 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/interactions/dispatcher.py +351 -337
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/interactions/specs.py +93 -3
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/leaf.py +56 -3
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/ops/derivative.py +41 -12
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/ops/slice.py +42 -3
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/params.py +25 -9
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/stateexpr.py +27 -3
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/trajectory/dataset.py +104 -63
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/trajectory/degrade.py +201 -64
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/trajectory/reserved_extras.py +29 -5
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/utils/formatting.py +32 -4
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/utils/maths.py +102 -7
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/utils/neighbors.py +11 -3
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/utils/plotting.py +253 -52
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/StochasticForceInference.egg-info/PKG-INFO +103 -44
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/StochasticForceInference.egg-info/SOURCES.txt +24 -1
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/StochasticForceInference.egg-info/requires.txt +3 -2
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/_gallery_utils/abp.py +7 -3
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/_gallery_utils/coarse_grain.py +26 -16
- stochasticforceinference-2.1.0/examples/_gallery_utils/janus_colloids.py +475 -0
- stochasticforceinference-2.1.0/examples/experimental_data/generate_tweezer_csv.py +53 -0
- stochasticforceinference-2.1.0/examples/gallery/abp_align_demo.py +456 -0
- stochasticforceinference-2.1.0/examples/gallery/abp_nonreciprocal_demo.py +606 -0
- stochasticforceinference-2.1.0/examples/gallery/abp_to_spde_demo.py +834 -0
- stochasticforceinference-2.1.0/examples/gallery/advanced/flocking_3d_demo.py +556 -0
- stochasticforceinference-2.1.0/examples/gallery/advanced/multi_experiment_demo.py +389 -0
- stochasticforceinference-2.1.0/examples/gallery/advanced/nn_force_demo.py +405 -0
- stochasticforceinference-2.1.0/examples/gallery/anisotropic_diffusion_demo.py +379 -0
- stochasticforceinference-2.1.0/examples/gallery/custom_basis_demo.py +327 -0
- stochasticforceinference-2.1.0/examples/gallery/diagnostics_demo.py +303 -0
- stochasticforceinference-2.1.0/examples/gallery/dynamics_order_demo.py +291 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/gallery/entropy_production_demo.py +152 -135
- stochasticforceinference-2.1.0/examples/gallery/entropy_production_underdamped_demo.py +493 -0
- stochasticforceinference-2.1.0/examples/gallery/experimental_workflow_demo.py +413 -0
- stochasticforceinference-2.1.0/examples/gallery/gray_scott_demo.py +711 -0
- stochasticforceinference-2.1.0/examples/gallery/home_range_demo.py +377 -0
- stochasticforceinference-2.1.0/examples/gallery/janus_colloids_demo.py +457 -0
- stochasticforceinference-2.1.0/examples/gallery/limitcycle_demo.py +328 -0
- stochasticforceinference-2.1.0/examples/gallery/lorenz_demo.py +369 -0
- stochasticforceinference-2.1.0/examples/gallery/lotka_volterra_demo.py +593 -0
- stochasticforceinference-2.1.0/examples/gallery/multiplicative_diffusion_demo.py +368 -0
- stochasticforceinference-2.1.0/examples/gallery/ou_demo.py +429 -0
- stochasticforceinference-2.1.0/examples/gallery/time_dependent_forcing_demo.py +268 -0
- stochasticforceinference-2.1.0/examples/gallery/time_fourier_demo.py +341 -0
- stochasticforceinference-2.1.0/examples/gallery/van_der_pol_demo.py +596 -0
- stochasticforceinference-2.1.0/examples/gallery/velocity_dependent_noise_demo.py +372 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/pyproject.toml +24 -8
- stochasticforceinference-2.1.0/tests/test_agent_guide.py +162 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/tests/test_parametric_mask_abp.py +1 -0
- stochasticforceinference-2.1.0/tests/test_version.py +50 -0
- stochasticforceinference-2.0.3/README.md +0 -163
- stochasticforceinference-2.0.3/SFI/inference/overdamped.py +0 -1497
- stochasticforceinference-2.0.3/SFI/inference/underdamped.py +0 -1857
- stochasticforceinference-2.0.3/SFI/integrate/integrand.py +0 -402
- stochasticforceinference-2.0.3/examples/experimental_data/generate_tweezer_csv.py +0 -35
- stochasticforceinference-2.0.3/examples/gallery/abp_align_demo.py +0 -574
- stochasticforceinference-2.0.3/examples/gallery/abp_nonreciprocal_demo.py +0 -529
- stochasticforceinference-2.0.3/examples/gallery/abp_to_spde_demo.py +0 -602
- stochasticforceinference-2.0.3/examples/gallery/advanced/flocking_3d_demo.py +0 -314
- stochasticforceinference-2.0.3/examples/gallery/advanced/multi_experiment_demo.py +0 -347
- stochasticforceinference-2.0.3/examples/gallery/advanced/nn_force_demo.py +0 -521
- stochasticforceinference-2.0.3/examples/gallery/anisotropic_diffusion_demo.py +0 -234
- stochasticforceinference-2.0.3/examples/gallery/custom_basis_demo.py +0 -254
- stochasticforceinference-2.0.3/examples/gallery/diagnostics_demo.py +0 -150
- stochasticforceinference-2.0.3/examples/gallery/dynamics_order_demo.py +0 -271
- stochasticforceinference-2.0.3/examples/gallery/entropy_production_underdamped_demo.py +0 -464
- stochasticforceinference-2.0.3/examples/gallery/experimental_workflow_demo.py +0 -216
- stochasticforceinference-2.0.3/examples/gallery/gray_scott_demo.py +0 -574
- stochasticforceinference-2.0.3/examples/gallery/home_range_demo.py +0 -394
- stochasticforceinference-2.0.3/examples/gallery/limitcycle_demo.py +0 -213
- stochasticforceinference-2.0.3/examples/gallery/lorenz_demo.py +0 -219
- stochasticforceinference-2.0.3/examples/gallery/lotka_volterra_demo.py +0 -319
- stochasticforceinference-2.0.3/examples/gallery/multiplicative_diffusion_demo.py +0 -240
- stochasticforceinference-2.0.3/examples/gallery/ou_demo.py +0 -413
- stochasticforceinference-2.0.3/examples/gallery/time_dependent_forcing_demo.py +0 -156
- stochasticforceinference-2.0.3/examples/gallery/time_fourier_demo.py +0 -234
- stochasticforceinference-2.0.3/examples/gallery/van_der_pol_demo.py +0 -245
- stochasticforceinference-2.0.3/examples/gallery/velocity_dependent_noise_demo.py +0 -202
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/CONTRIBUTING.md +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/GALLERY_STYLE_GUIDE.md +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/LICENSE +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/bases/__init__.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/bases/constants.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/bases/linear.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/bases/monomials.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/bases/spde.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/optimizers.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/parametric_core/__init__.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/parametric_core/banded.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/parametric_core/covariance.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/parametric_core/flow.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/parametric_core/flow_ud.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/parametric_core/gram.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/parametric_core/jacobians.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/serialization.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/sparse/base.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/sparse/beam.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/sparse/greedy.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/sparse/lasso.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/sparse/metrics.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/sparse/scorer.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/sparse/stlsq.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/inference/sparsity.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/integrate/rk4.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/langevin/__init__.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/__init__.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/basis.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/core/runtime.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/interactor.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/layout/__init__.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/layout/_base.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/layout/_eval_compiler.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/layout/_fd_atoms.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/layout/_grid.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/layout/_sectors.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/memhint.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/__init__.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/contract.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/interactions/prepare.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/interactions/stencils.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/ops/__init__.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/ops/concat.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/ops/einsum.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/ops/linear.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/ops/mapn.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/nodes/ops/reshape_rank.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/psf.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/sf.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/statefunc/structexpr.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/trajectory/__init__.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/trajectory/collection.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/trajectory/io.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/SFI/utils/__init__.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/StochasticForceInference.egg-info/dependency_links.txt +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/StochasticForceInference.egg-info/top_level.txt +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/_gallery_utils/__init__.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/_gallery_utils/bench_utils.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/_gallery_utils/helpers.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/_gallery_utils/scenario_picker.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/experimental_data/_analyze_results.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/experimental_data/_expanded_basis.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/manual_examples/abp_align_demo.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/manual_examples/abp_largescale_config.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/manual_examples/abp_largescale_demo.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/manual_examples/abp_largescale_infer.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/manual_examples/abp_largescale_plot.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/manual_examples/abp_largescale_simulate.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/examples/manual_examples/abp_pursuit_demo.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/setup.cfg +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/tests/test_dual_mask.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/tests/test_parametric_mask.py +0 -0
- {stochasticforceinference-2.0.3 → stochasticforceinference-2.1.0}/tests/test_same_particle_jacobian.py +0 -0
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
> agents (GitHub Copilot, Claude Code, Cursor, …) on the Stochastic
|
|
5
5
|
> Force Inference (SFI) repository. Human contributors should read
|
|
6
6
|
> [`CONTRIBUTING.md`](CONTRIBUTING.md).
|
|
7
|
+
>
|
|
8
|
+
> **Using SFI as a library** (analysing data, not modifying SFI)? Read
|
|
9
|
+
> [`SFI/AGENT_GUIDE.md`](SFI/AGENT_GUIDE.md) instead: it ships inside the
|
|
10
|
+
> installed package (`python -m SFI guide`).
|
|
7
11
|
|
|
8
12
|
---
|
|
9
13
|
|
|
@@ -45,6 +49,8 @@ SFI has mature, well-tested abstractions for every common operation.
|
|
|
45
49
|
| Wrap a user function as a state function | `SFI.statefunc.make_basis` / `make_sf` / `make_psf` |
|
|
46
50
|
| Run force / diffusion inference | `SFI.OverdampedLangevinInference` / `UnderdampedLangevinInference` |
|
|
47
51
|
| Select a sparse model | `inf.sparsify_force(criterion="PASTIS", p=0.1)` |
|
|
52
|
+
| Select a sparse diffusion model | `inf.sparsify_diffusion(criterion="PASTIS", p=0.05)` |
|
|
53
|
+
| Keep terms in every model / select grouped terms together | `inf.sparsify_force(protected=[...], groups={...})` (indices or `basis.labels`; also `sparsify_diffusion`) |
|
|
48
54
|
| Compare to ground truth | `inf.compare_to_exact(model_exact=...)` |
|
|
49
55
|
| Plot in the SFI style | `SFI.utils.plotting.SFI_COLORS`, `dark_fig`, `phase2d` |
|
|
50
56
|
| Save / load a fitted model | `SFI.inference.save_model` / `load_model` |
|
|
@@ -78,6 +84,37 @@ from SFI import (
|
|
|
78
84
|
The dynamics-order classifier (`classify_dynamics`, returning a
|
|
79
85
|
`DynamicsOrderReport`) decides overdamped vs underdamped from raw
|
|
80
86
|
positions; see `SFI.diagnostics` and `examples/gallery/dynamics_order_demo.py`.
|
|
87
|
+
`SFI.diagnostics.finite_dt_scale(inf)` reports the per-step drift-gradient
|
|
88
|
+
scale Δt‖∇F̂‖ of a fitted force (the size of the linear estimators' O(Δt)
|
|
89
|
+
biases) with a `fine` / `coarse` / `unreliable` verdict; `assess(inf)` includes
|
|
90
|
+
it and flags the coarse regimes. For underdamped linear fits with the default
|
|
91
|
+
constant diffusion, `assess(inf)` also compares it with the drift-corrected one
|
|
92
|
+
(`report.diffusion`: difference, z, chi-squared p-value; one pass with the fitted
|
|
93
|
+
force), the check `compute_diffusion_constant(method="drift-corrected")` runs and
|
|
94
|
+
stores when it replaces the default. Both linear engines also record the force
|
|
95
|
+
Gram condition number (`metadata["force_gram_cond"]`) and warn when the
|
|
96
|
+
dictionary is ill-conditioned on the data; the underdamped linear
|
|
97
|
+
estimators also warn on non-uniform frame intervals
|
|
98
|
+
(`metadata["dt_mismatch_rms"]`), which they do not support. After an
|
|
99
|
+
underdamped linear fit, `compute_force_error()` also checks the basis's
|
|
100
|
+
path resolution (`metadata["force_path_resolution"]`: features that vary
|
|
101
|
+
along the motion within a stencil, their attenuation `kappa` and predicted
|
|
102
|
+
bias in error bars; it warns when a bias exceeds its error bar). Under
|
|
103
|
+
strong localisation noise at fine sampling (`metadata["force_noise_ratio"]`
|
|
104
|
+
>= 1, warned), fit with `infer_force_linear(B, stride="auto")` (experimental)
|
|
105
|
+
(`preset="model-free"` / `"constant-noise"`): it picks the frame stride
|
|
106
|
+
(`metadata["force_stride_scan"]`). Estimate the diffusion constant the same
|
|
107
|
+
way, `compute_diffusion_constant(stride="auto")`
|
|
108
|
+
(`metadata["diffusion_constant_stride_scan"]`): at stride 1 its sign is
|
|
109
|
+
random once the noise ratio exceeds about sqrt(rows), and the force fit
|
|
110
|
+
needs a positive definite constant. The diffusion field likewise:
|
|
111
|
+
`infer_diffusion_linear(B_D, stride="auto")`
|
|
112
|
+
(`metadata["diffusion_stride_scan"]`). A selected stride above 1 warns with
|
|
113
|
+
its reason.
|
|
114
|
+
`SFI.diagnostics.psd_fraction(D_sf, coll)` reports the fraction of data
|
|
115
|
+
points where a diffusion field is not positive semi-definite;
|
|
116
|
+
`simulate_bootstrapped_trajectory` runs it on the fitted diffusion and warns
|
|
117
|
+
(the simulator clips negative eigenvalues silently).
|
|
81
118
|
|
|
82
119
|
### 4.2 `SFI.statefunc` — composable state functions
|
|
83
120
|
|
|
@@ -89,7 +126,7 @@ positions; see `SFI.diagnostics` and `examples/gallery/dynamics_order_demo.py`.
|
|
|
89
126
|
| `make_sf(func, dim, rank, ...)` | Wrap a Python callable as an `SF` |
|
|
90
127
|
| `make_psf(func, dim, rank, ...)` | Wrap a callable with parameters as `PSF` |
|
|
91
128
|
| `make_basis(func, dim, ...)` | Wrap a vector-valued callable as `Basis` |
|
|
92
|
-
| `Interactor`, `make_interactor` | Multi-scale interaction graphs
|
|
129
|
+
| `Interactor`, `make_interactor` | Multi-scale interaction graphs (pairs, hyperedges; `per_slot=True` for many-body forces) |
|
|
93
130
|
|
|
94
131
|
### 4.3 `SFI.inference` — inference engines
|
|
95
132
|
|
|
@@ -134,7 +171,7 @@ agreement is itself a diagnostic.
|
|
|
134
171
|
| `inf.print_report()` / `inf.report_dict()` | Human / machine summary |
|
|
135
172
|
| `inf.compare_to_exact(model_exact=...)` | Validate against a known model |
|
|
136
173
|
| `inf.holdout_score(test)` | Held-out NMSE on `coll.split_time(...)` test data (data-abundant scenarios only) |
|
|
137
|
-
| `inf.compute_entropy_production()` | Dissipation of the observed dynamics (after a linear force fit; both engines): rate ± error + fluctuation bias and the AIC-debiased rate (`Sdot_debiased`), in k_B. Underdamped: positions-only via the even/odd split; `coefficients=` enables cross-fitting |
|
|
174
|
+
| `inf.compute_entropy_production()` | Dissipation of the observed dynamics (after a linear force fit; both engines): rate ± error + fluctuation bias and the AIC-debiased rate (`Sdot_debiased`), in k_B. Underdamped: positions-only via the even/odd split; `coefficients=` enables cross-fitting, `jackknife=True` the delete-half jackknife (`Sdot_jackknife`, free of the plug-in bias) |
|
|
138
175
|
| `inf.time_reversal_split()` | Underdamped only: the fitted field's reversible/irreversible parts `(F_even, F_odd)` as callables |
|
|
139
176
|
|
|
140
177
|
* **Parametric estimators (robust, flexible; compute-intensive).**
|
|
@@ -179,14 +216,14 @@ agreement is itself a diagnostic.
|
|
|
179
216
|
|
|
180
217
|
```python
|
|
181
218
|
inf = OverdampedLangevinInference(collection)
|
|
182
|
-
inf.
|
|
183
|
-
|
|
184
|
-
inf.infer_diffusion_linear() #
|
|
185
|
-
inf.compute_force_error() #
|
|
186
|
-
inf.sparsify_force(criterion="PASTIS", p=0.1) #
|
|
187
|
-
inf.compute_entropy_production() #
|
|
188
|
-
inf.print_report() #
|
|
189
|
-
inf.compare_to_exact(model_exact=process) #
|
|
219
|
+
inf.infer_force_linear(basis) # 1. force (overdamped preset "instrument" default/"legacy-robust"/"legacy-clean"/"legacy-KM"/"legacy-noisy-v1.0", "auto" retired: fit it FIRST, it sets the drift-corrected constant D-bar and Lambda; underdamped "model-free" default/"constant-noise"/"legacy-robust"/"legacy-clean"/legacy v1.0, after compute_diffusion_constant())
|
|
220
|
+
# constant D otherwise: overdamped compute_diffusion_constant() (default "noisy"; "WeakNoise"/"MSD" by name) only to keep a stencil D (a prior call keeps it), method="drift-corrected" after step 1; underdamped compute_diffusion_constant() before step 1 (default "model-free", legacy stencils by name, "drift-corrected" after step 1)
|
|
221
|
+
inf.infer_diffusion_linear() # 2. optional: diffusion field (overdamped: basis optional, default = constant sym D; default "drift-corrected" = regressed on the force's residuals, needs step 1; underdamped: basis required, default "model-free", "drift-corrected" after step 1; M_mode= selects the legacy fit in both)
|
|
222
|
+
inf.compute_force_error() # 3. error analysis
|
|
223
|
+
inf.sparsify_force(criterion="PASTIS", p=0.1) # 4. optional: sparsity
|
|
224
|
+
inf.compute_entropy_production() # 5. optional: dissipation (OD & UD)
|
|
225
|
+
inf.print_report() # 6. summary
|
|
226
|
+
inf.compare_to_exact(model_exact=process) # 7. optional: validate
|
|
190
227
|
```
|
|
191
228
|
|
|
192
229
|
**Parametric-estimator sequence:**
|
|
@@ -200,10 +237,19 @@ inf.compute_force_error()
|
|
|
200
237
|
|
|
201
238
|
**Sparsity.** PASTIS is the canonical criterion in SFI. Alternative
|
|
202
239
|
criteria (`AIC`, `BIC`, `SIC`) and strategies (greedy stepwise,
|
|
203
|
-
STLSQ, LASSO
|
|
240
|
+
STLSQ, LASSO, `method="exhaustive"` for the exact front of small
|
|
241
|
+
candidate sets) are available — see
|
|
204
242
|
[`_project_index/api_map.md`](_project_index/api_map.md#sfiinferencesparse)
|
|
205
243
|
for the full inventory. Precision/recall and held-out NMSE helpers
|
|
206
244
|
live in `SFI.inference.sparse.overlap_metrics` and `predictive_nmse`.
|
|
245
|
+
`protected=` keeps functions in every model (not candidates: nuisance
|
|
246
|
+
blocks, a required friction) and `groups=` makes functions enter and
|
|
247
|
+
leave together (a harmonic's `(cos, sin)` pair, per-dataset copies); the
|
|
248
|
+
search then runs over units (`UnitScorer`), `k`/`max_k` count units, and
|
|
249
|
+
PASTIS charges a group of `m` parameters `pastis_unit_penalty(m, n0, p)`
|
|
250
|
+
(the exact chi-squared quantile at a single term's false-inclusion level;
|
|
251
|
+
`ln(n0/p)` for `m = 1`). `SparsityResult.selected()` returns the chosen
|
|
252
|
+
model with its information, parameter count and unit names.
|
|
207
253
|
|
|
208
254
|
### 4.4 `SFI.trajectory` — data containers
|
|
209
255
|
|
|
@@ -354,6 +400,21 @@ Deprecated / soon-to-be-removed symbols (do not use in new code):
|
|
|
354
400
|
deprecated tuning knobs, accepted but **inert** (a
|
|
355
401
|
`DeprecationWarning` fires when set). The banded likelihood has no
|
|
356
402
|
window truncation to tune.
|
|
403
|
+
- Underdamped `infer_force_linear(preset="auto" | "robust" | "clean")` —
|
|
404
|
+
retired names, accepted with a `FutureWarning`: `"auto"` runs the
|
|
405
|
+
default `"model-free"` (combined with explicit `M_mode` / `G_mode` /
|
|
406
|
+
`diffusion_method` / `cross_particle` it raises: name a `legacy-` preset); `"robust"` / `"clean"` are
|
|
407
|
+
now `"legacy-robust"` / `"legacy-clean"`. Mode overrides apply to the
|
|
408
|
+
`legacy-` presets only; without a preset they warn and will raise.
|
|
409
|
+
- Underdamped `compute_diffusion_constant(method="auto")` — retired, accepted
|
|
410
|
+
with a `FutureWarning`: runs the default `"model-free"` (the mean of the
|
|
411
|
+
model-free force design's per-frame diffusion). The former choice
|
|
412
|
+
(`"noisy"` when `Tr Lambda > 0`, else `"WeakNoise"`) is available by name.
|
|
413
|
+
- Overdamped `infer_force_linear(preset="auto")` — retired, accepted with a
|
|
414
|
+
`FutureWarning`: runs the default `"instrument"`. Its former choice
|
|
415
|
+
(`"robust"` when `Tr Lambda > 0`, else `"clean"`) is available by name;
|
|
416
|
+
mode arguments without a preset are still completed that way
|
|
417
|
+
(`SharedNoiseOLI` keeps that choice as its default).
|
|
357
418
|
|
|
358
419
|
## 6. Testing, building, environment
|
|
359
420
|
|
|
@@ -363,6 +424,7 @@ Full details: [`docs/source/dev_notes.rst`](docs/source/dev_notes.rst).
|
|
|
363
424
|
source .venv/bin/activate
|
|
364
425
|
pytest tests/ -v # full suite (CPU-only via conftest)
|
|
365
426
|
pytest tests/ -x --ff # quick smoke
|
|
427
|
+
pytest tests/inference -m sparsity # when changing sparse selection (deselected by default)
|
|
366
428
|
cd docs && make clean && make html # fast docs build
|
|
367
429
|
cd docs && SFI_DOCS_RUN_GALLERY=1 make html # full build (slow)
|
|
368
430
|
```
|
|
@@ -4,6 +4,7 @@ recursive-include examples *.py
|
|
|
4
4
|
# Top-level docs we want shipped
|
|
5
5
|
include README.md LICENSE pyproject.toml setup.cfg
|
|
6
6
|
include AGENTS.md CONTRIBUTING.md GALLERY_STYLE_GUIDE.md
|
|
7
|
+
include SFI/AGENT_GUIDE.md
|
|
7
8
|
|
|
8
9
|
# Exclude common junk files
|
|
9
10
|
global-exclude *.csv *.mp4 *.pkl *.npz *.npy *~ *.bak
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: StochasticForceInference
|
|
3
|
-
Version: 2.0
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 2.1.0
|
|
4
|
+
Summary: Learn stochastic differential equations (Langevin dynamics: drift/force and diffusion) from time series and trajectory data
|
|
5
5
|
Author-email: Pierre Ronceray <pierre.ronceray@univ-amu.fr>
|
|
6
6
|
License: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/ronceray/StochasticForceInference
|
|
8
8
|
Project-URL: Documentation, https://stochasticforceinference.readthedocs.io
|
|
9
|
+
Project-URL: Gallery, https://stochasticforceinference.readthedocs.io/en/stable/gallery/index.html
|
|
10
|
+
Project-URL: Guide for AI agents, https://github.com/ronceray/StochasticForceInference/blob/main/SFI/AGENT_GUIDE.md
|
|
9
11
|
Project-URL: Repository, https://github.com/ronceray/StochasticForceInference
|
|
10
12
|
Project-URL: Issues, https://github.com/ronceray/StochasticForceInference/issues
|
|
11
13
|
Project-URL: Changelog, https://github.com/ronceray/StochasticForceInference/blob/main/CHANGELOG.md
|
|
12
|
-
Keywords: stochastic force inference,Langevin dynamics,stochastic differential equations,diffusion,inference,sparse model selection,active matter,biophysics,JAX
|
|
14
|
+
Keywords: stochastic force inference,Langevin dynamics,stochastic differential equations,SDE,diffusion,inference,drift estimation,diffusion estimation,Kramers-Moyal,Fokker-Planck,time series,trajectory analysis,system identification,equation discovery,sparse model selection,particle tracking,single-particle tracking,cell migration,population dynamics,gene expression,entropy production,Ornstein-Uhlenbeck,active matter,biophysics,JAX
|
|
13
15
|
Classifier: Development Status :: 5 - Production/Stable
|
|
14
16
|
Classifier: Intended Audience :: Science/Research
|
|
15
17
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -20,13 +22,14 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
20
22
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
23
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
22
24
|
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
25
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
23
26
|
Requires-Python: >=3.11
|
|
24
27
|
Description-Content-Type: text/markdown
|
|
25
28
|
License-File: LICENSE
|
|
26
29
|
Requires-Dist: numpy
|
|
27
30
|
Requires-Dist: scipy
|
|
28
|
-
Requires-Dist: jax
|
|
29
|
-
Requires-Dist: jaxlib
|
|
31
|
+
Requires-Dist: jax!=0.10.2,!=0.11.0,>=0.10.1
|
|
32
|
+
Requires-Dist: jaxlib!=0.10.2,!=0.11.0,>=0.10.1
|
|
30
33
|
Requires-Dist: pandas
|
|
31
34
|
Requires-Dist: matplotlib
|
|
32
35
|
Requires-Dist: pyyaml
|
|
@@ -42,6 +45,7 @@ Requires-Dist: sphinxcontrib-video; extra == "docs"
|
|
|
42
45
|
Requires-Dist: sphinxcontrib-mermaid; extra == "docs"
|
|
43
46
|
Provides-Extra: dev
|
|
44
47
|
Requires-Dist: pytest; extra == "dev"
|
|
48
|
+
Requires-Dist: pytest-xdist; extra == "dev"
|
|
45
49
|
Requires-Dist: ruff; extra == "dev"
|
|
46
50
|
Requires-Dist: pyright; extra == "dev"
|
|
47
51
|
Requires-Dist: StochasticForceInference[docs]; extra == "dev"
|
|
@@ -57,14 +61,38 @@ Dynamic: license-file
|
|
|
57
61
|
[](https://stochasticforceinference.readthedocs.io/en/latest/)
|
|
58
62
|
[](https://pypi.org/project/StochasticForceInference/)
|
|
59
63
|
[](https://github.com/ronceray/StochasticForceInference/blob/main/LICENSE)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
[](https://doi.org/10.5281/zenodo.21532842)
|
|
65
|
+
|
|
66
|
+
**Learn the stochastic equation behind your time series.**
|
|
67
|
+
|
|
68
|
+
SFI is a JAX-based Python package that infers the drift (force) and
|
|
69
|
+
diffusion of Langevin stochastic differential equations from trajectories
|
|
70
|
+
and other continuous time series: tracked particles, cells and animals,
|
|
71
|
+
population abundances, gene-expression and other molecular levels,
|
|
72
|
+
concentration fields. It returns an interpretable
|
|
73
|
+
equation with error bars, selects the terms the data supports, and
|
|
74
|
+
simulates the fitted model. It handles overdamped and underdamped
|
|
75
|
+
dynamics, interacting particles and spatially extended (SPDE) systems.
|
|
76
|
+
|
|
77
|
+
## Is SFI for my data?
|
|
78
|
+
|
|
79
|
+
| You want to… | SFI does it with |
|
|
80
|
+
| --- | --- |
|
|
81
|
+
| estimate drift and diffusion (first and second Kramers–Moyal coefficients, a Fokker–Planck model) | `OverdampedLangevinInference`: `infer_force_linear`, `infer_diffusion_linear` |
|
|
82
|
+
| discover the equation of a noisy stochastic system (sparse regression, "stochastic SINDy") | a candidate basis + `sparsify_force(criterion="PASTIS")` |
|
|
83
|
+
| map forces and diffusivity from single-particle tracking, with localization error | the overdamped engine; the defaults correct white localization noise |
|
|
84
|
+
| model cell migration, animal movement or active particles (persistent velocities) | `UnderdampedLangevinInference`, from positions alone |
|
|
85
|
+
| measure interaction forces between particles, collective motion | pair bases (`SFI.bases.pairs`) |
|
|
86
|
+
| model population dynamics: microbial or ecological abundances, growth rates, species interactions | the overdamped engine on log-abundances + `sparsify_force` ([Lotka–Volterra example](https://stochasticforceinference.readthedocs.io/en/stable/gallery/lotka_volterra_demo.html)) |
|
|
87
|
+
| model gene-expression, protein or metabolite levels, whose noise scales with the level | the overdamped engine with a diffusion field `D(x)` (`infer_diffusion_linear`) |
|
|
88
|
+
| fit noisy oscillators and chaotic signals (genetic or circadian clocks, hair bundles) | a nonlinear basis; `UnderdampedLangevinInference` when one coordinate of an inertial oscillator is observed |
|
|
89
|
+
| quantify irreversibility: entropy production, broken detailed balance | `compute_entropy_production()` |
|
|
90
|
+
| decide whether the dynamics are overdamped or underdamped | `SFI.classify_dynamics` |
|
|
91
|
+
|
|
92
|
+
SFI is not the right tool for categorical data, small counts or events, for
|
|
93
|
+
forecasting without an equation, for snapshots without time correlation,
|
|
94
|
+
or for processes with jumps. More routes:
|
|
95
|
+
[Start here](https://stochasticforceinference.readthedocs.io/en/stable/start_here.html).
|
|
68
96
|
|
|
69
97
|
> **Designed for experimental data.** SFI is built for real experimental
|
|
70
98
|
> trajectories (tracked particles, cells, organisms, …) where *no dynamical
|
|
@@ -78,10 +106,11 @@ diagnostics, sparse model selection, and bootstrapped validation.
|
|
|
78
106
|
## Key features
|
|
79
107
|
|
|
80
108
|
- **Two estimator families** — closed-form linear estimators
|
|
81
|
-
(`infer_force_linear`, seconds even on large datasets
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
109
|
+
(`infer_force_linear`, seconds even on large datasets; the defaults
|
|
110
|
+
correct localization noise and the leading finite-time-step bias) and
|
|
111
|
+
parametric estimators (`infer_force` / `infer_diffusion`: noise-aware
|
|
112
|
+
likelihood fit, robust to localization error and coarse sampling,
|
|
113
|
+
accepts nonlinear models such as neural-network drifts).
|
|
85
114
|
- **Overdamped & underdamped inference** — works with position-only data;
|
|
86
115
|
velocities are reconstructed automatically for underdamped systems.
|
|
87
116
|
- **Composable state functions** — build force/diffusion models from
|
|
@@ -89,18 +118,21 @@ diagnostics, sparse model selection, and bootstrapped validation.
|
|
|
89
118
|
parametric families, all with automatic differentiation via JAX.
|
|
90
119
|
- **Sparse model selection** — Pareto-front beam search with AIC / BIC /
|
|
91
120
|
PASTIS information criteria.
|
|
92
|
-
- **
|
|
93
|
-
|
|
121
|
+
- **Entropy production** — dissipation rate with error bar, for
|
|
122
|
+
overdamped and underdamped dynamics.
|
|
123
|
+
- **Simulation** — simulate Langevin SDEs from the same model objects
|
|
124
|
+
used for inference, including bootstrapped trajectories of a fitted model.
|
|
94
125
|
- **Trajectory toolkit** — mask-aware increments, synthetic degradation
|
|
95
126
|
(noise, downsampling, data loss, motion blur), streaming for large
|
|
96
|
-
datasets, I/O (CSV / Parquet / HDF5).
|
|
97
|
-
- **Diagnostics** —
|
|
98
|
-
|
|
127
|
+
datasets, I/O (CSV / Parquet / HDF5, tracking tables).
|
|
128
|
+
- **Diagnostics** — residual tests with action hints, an
|
|
129
|
+
overdamped-vs-underdamped classifier, predicted errors, comparison to
|
|
130
|
+
exact models.
|
|
99
131
|
|
|
100
132
|
## Installation
|
|
101
133
|
|
|
102
134
|
```bash
|
|
103
|
-
pip install StochasticForceInference
|
|
135
|
+
pip install StochasticForceInference # import name: SFI
|
|
104
136
|
```
|
|
105
137
|
|
|
106
138
|
For development (editable install with test/doc dependencies):
|
|
@@ -129,12 +161,13 @@ coll = TrajectoryCollection.from_arrays(X=positions, dt=0.01)
|
|
|
129
161
|
# Infer using a polynomial basis — no model needed
|
|
130
162
|
B = monomials_up_to(order=3, dim=2, rank="vector")
|
|
131
163
|
inf = OverdampedLangevinInference(coll)
|
|
132
|
-
inf.
|
|
133
|
-
inf.infer_force_linear(B)
|
|
164
|
+
inf.infer_force_linear(B) # also estimates D and the measurement noise
|
|
134
165
|
inf.sparsify_force(criterion="PASTIS") # optional: find the minimal model
|
|
135
|
-
inf.
|
|
166
|
+
inf.compute_force_error()
|
|
167
|
+
inf.print_report() # coefficients with error bars
|
|
168
|
+
inf.diagnose().print_summary() # residual tests, with hints if one fails
|
|
136
169
|
|
|
137
|
-
#
|
|
170
|
+
# Coarsely sampled or very noisy recordings? Use the parametric estimator
|
|
138
171
|
# instead: inf.infer_force(B) — it models the measurement noise natively.
|
|
139
172
|
```
|
|
140
173
|
|
|
@@ -157,7 +190,6 @@ coll = proc.simulate(dt=0.01, Nsteps=10_000, key=random.PRNGKey(0))
|
|
|
157
190
|
# 2. Infer from the trajectory using a generic polynomial basis
|
|
158
191
|
B = monomials_up_to(order=2, dim=2, rank="vector")
|
|
159
192
|
inf = OverdampedLangevinInference(coll)
|
|
160
|
-
inf.compute_diffusion_constant()
|
|
161
193
|
inf.infer_force_linear(B)
|
|
162
194
|
inf.compute_force_error()
|
|
163
195
|
|
|
@@ -166,11 +198,35 @@ inf.print_report()
|
|
|
166
198
|
inf.compare_to_exact(model_exact=proc)
|
|
167
199
|
```
|
|
168
200
|
|
|
201
|
+
## Using SFI with an AI agent
|
|
202
|
+
|
|
203
|
+
SFI ships a workflow guide for AI coding agents (Claude Code, Codex,
|
|
204
|
+
Cursor, …) inside the package, matched to the installed version:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
python -m SFI guide # Markdown: workflow, decisions, pitfalls, API names
|
|
208
|
+
|
|
209
|
+
# Install it as an Agent Skill (path shown for Claude Code; other tools that support skills use their own folder)
|
|
210
|
+
mkdir -p ~/.claude/skills/stochastic-force-inference
|
|
211
|
+
python -m SFI guide --skill > ~/.claude/skills/stochastic-force-inference/SKILL.md
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
The documentation has an [`llms.txt`](https://stochasticforceinference.readthedocs.io/llms.txt)
|
|
215
|
+
index. Agents that modify SFI itself should read
|
|
216
|
+
[`AGENTS.md`](https://github.com/ronceray/StochasticForceInference/blob/main/AGENTS.md).
|
|
217
|
+
|
|
218
|
+
**Coming from the original SFI scripts** (`StochasticForceInference.py`,
|
|
219
|
+
`StochasticTrajectoryData`, or the separate UnderdampedLangevinInference
|
|
220
|
+
package)? SFI 2 is a rewrite with a new API; the
|
|
221
|
+
[guide](https://github.com/ronceray/StochasticForceInference/blob/main/SFI/AGENT_GUIDE.md#9-coming-from-the-original-sfi-scripts-or-older-example-code)
|
|
222
|
+
maps the old calls to the new ones.
|
|
223
|
+
|
|
169
224
|
## Documentation
|
|
170
225
|
|
|
171
226
|
Full documentation is available at
|
|
172
227
|
[stochasticforceinference.readthedocs.io](https://stochasticforceinference.readthedocs.io), including:
|
|
173
228
|
|
|
229
|
+
- **[Start here](https://stochasticforceinference.readthedocs.io/en/latest/start_here.html)** — is SFI right for my data, and which route to take
|
|
174
230
|
- **[Tutorial](https://stochasticforceinference.readthedocs.io/en/latest/gallery/ou_demo.html)** — end-to-end walkthrough
|
|
175
231
|
- **[Examples gallery](https://stochasticforceinference.readthedocs.io/en/latest/gallery/index.html)** — worked examples covering sparsity, multi-particle, and SPDE inference
|
|
176
232
|
- **[Model building](https://stochasticforceinference.readthedocs.io/en/latest/statefunc/user_guide.html)** — composable state functions
|
|
@@ -180,25 +236,28 @@ Full documentation is available at
|
|
|
180
236
|
|
|
181
237
|
## Package structure
|
|
182
238
|
|
|
183
|
-
| Subpackage
|
|
184
|
-
|
|
|
185
|
-
| `SFI.statefunc`
|
|
186
|
-
| `SFI.inference`
|
|
187
|
-
| `SFI.trajectory`
|
|
188
|
-
| `SFI.langevin`
|
|
189
|
-
| `SFI.bases`
|
|
190
|
-
| `SFI.
|
|
191
|
-
| `SFI.
|
|
192
|
-
|
|
193
|
-
For contributors and AI coding agents: see [`AGENTS.md`](https://github.com/ronceray/StochasticForceInference/blob/main/AGENTS.md) for
|
|
194
|
-
the canonical imports table, task playbooks, and "do not re-implement"
|
|
195
|
-
guidance.
|
|
239
|
+
| Subpackage | Purpose |
|
|
240
|
+
| ----------------- | ---------------------------------------------------- |
|
|
241
|
+
| `SFI.statefunc` | Composable state functions: `Basis`, `PSF`, `SF` |
|
|
242
|
+
| `SFI.inference` | Overdamped & underdamped inference engines |
|
|
243
|
+
| `SFI.trajectory` | `TrajectoryCollection` / `TrajectoryDataset` |
|
|
244
|
+
| `SFI.langevin` | Langevin simulators (`OverdampedProcess`, …) |
|
|
245
|
+
| `SFI.bases` | Ready-made basis builders (monomials, pairs, SPDE, …) |
|
|
246
|
+
| `SFI.diagnostics` | Residual tests, dynamics classifier, error checks |
|
|
247
|
+
| `SFI.integrate` | Time-averaging integration engine |
|
|
248
|
+
| `SFI.utils` | Math helpers, formatting, plotting |
|
|
196
249
|
|
|
197
250
|
## Citation
|
|
198
251
|
|
|
199
|
-
If you use SFI, please cite the software (see [`CITATION.cff`](CITATION.cff))
|
|
200
|
-
together with the method paper(s) relevant to the features you use.
|
|
201
|
-
|
|
252
|
+
If you use SFI, please cite the software (see [`CITATION.cff`](https://github.com/ronceray/StochasticForceInference/blob/main/CITATION.cff))
|
|
253
|
+
together with the method paper(s) relevant to the features you use.
|
|
254
|
+
|
|
255
|
+
The software is archived on Zenodo. Cite the concept DOI
|
|
256
|
+
[10.5281/zenodo.21532842](https://doi.org/10.5281/zenodo.21532842), which always
|
|
257
|
+
resolves to the latest release; each version also has its own DOI (v2.0.4:
|
|
258
|
+
[10.5281/zenodo.23498743](https://doi.org/10.5281/zenodo.23498743)).
|
|
259
|
+
|
|
260
|
+
See **[How to cite](https://stochasticforceinference.readthedocs.io/en/latest/#how-to-cite)** in the
|
|
202
261
|
documentation for the full, feature-specific list (overdamped, underdamped/ULI,
|
|
203
262
|
trapeze, and PASTIS references).
|
|
204
263
|
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Stochastic Force Inference (SFI)
|
|
2
|
+
|
|
3
|
+
[](https://stochasticforceinference.readthedocs.io/en/latest/)
|
|
4
|
+
[](https://pypi.org/project/StochasticForceInference/)
|
|
5
|
+
[](https://github.com/ronceray/StochasticForceInference/blob/main/LICENSE)
|
|
6
|
+
[](https://doi.org/10.5281/zenodo.21532842)
|
|
7
|
+
|
|
8
|
+
**Learn the stochastic equation behind your time series.**
|
|
9
|
+
|
|
10
|
+
SFI is a JAX-based Python package that infers the drift (force) and
|
|
11
|
+
diffusion of Langevin stochastic differential equations from trajectories
|
|
12
|
+
and other continuous time series: tracked particles, cells and animals,
|
|
13
|
+
population abundances, gene-expression and other molecular levels,
|
|
14
|
+
concentration fields. It returns an interpretable
|
|
15
|
+
equation with error bars, selects the terms the data supports, and
|
|
16
|
+
simulates the fitted model. It handles overdamped and underdamped
|
|
17
|
+
dynamics, interacting particles and spatially extended (SPDE) systems.
|
|
18
|
+
|
|
19
|
+
## Is SFI for my data?
|
|
20
|
+
|
|
21
|
+
| You want to… | SFI does it with |
|
|
22
|
+
| --- | --- |
|
|
23
|
+
| estimate drift and diffusion (first and second Kramers–Moyal coefficients, a Fokker–Planck model) | `OverdampedLangevinInference`: `infer_force_linear`, `infer_diffusion_linear` |
|
|
24
|
+
| discover the equation of a noisy stochastic system (sparse regression, "stochastic SINDy") | a candidate basis + `sparsify_force(criterion="PASTIS")` |
|
|
25
|
+
| map forces and diffusivity from single-particle tracking, with localization error | the overdamped engine; the defaults correct white localization noise |
|
|
26
|
+
| model cell migration, animal movement or active particles (persistent velocities) | `UnderdampedLangevinInference`, from positions alone |
|
|
27
|
+
| measure interaction forces between particles, collective motion | pair bases (`SFI.bases.pairs`) |
|
|
28
|
+
| model population dynamics: microbial or ecological abundances, growth rates, species interactions | the overdamped engine on log-abundances + `sparsify_force` ([Lotka–Volterra example](https://stochasticforceinference.readthedocs.io/en/stable/gallery/lotka_volterra_demo.html)) |
|
|
29
|
+
| model gene-expression, protein or metabolite levels, whose noise scales with the level | the overdamped engine with a diffusion field `D(x)` (`infer_diffusion_linear`) |
|
|
30
|
+
| fit noisy oscillators and chaotic signals (genetic or circadian clocks, hair bundles) | a nonlinear basis; `UnderdampedLangevinInference` when one coordinate of an inertial oscillator is observed |
|
|
31
|
+
| quantify irreversibility: entropy production, broken detailed balance | `compute_entropy_production()` |
|
|
32
|
+
| decide whether the dynamics are overdamped or underdamped | `SFI.classify_dynamics` |
|
|
33
|
+
|
|
34
|
+
SFI is not the right tool for categorical data, small counts or events, for
|
|
35
|
+
forecasting without an equation, for snapshots without time correlation,
|
|
36
|
+
or for processes with jumps. More routes:
|
|
37
|
+
[Start here](https://stochasticforceinference.readthedocs.io/en/stable/start_here.html).
|
|
38
|
+
|
|
39
|
+
> **Designed for experimental data.** SFI is built for real experimental
|
|
40
|
+
> trajectories (tracked particles, cells, organisms, …) where *no dynamical
|
|
41
|
+
> model pre-exists*. Two first-class estimator families share one API:
|
|
42
|
+
> fast closed-form **linear estimators** that require no initial guess, and
|
|
43
|
+
> **parametric estimators** that model measurement noise and finite sampling
|
|
44
|
+
> explicitly — robust where real data is hard. The PASTIS information
|
|
45
|
+
> criterion rigorously identifies which terms the data actually supports.
|
|
46
|
+
> Synthetic examples in the gallery serve as runnable demonstrations.
|
|
47
|
+
|
|
48
|
+
## Key features
|
|
49
|
+
|
|
50
|
+
- **Two estimator families** — closed-form linear estimators
|
|
51
|
+
(`infer_force_linear`, seconds even on large datasets; the defaults
|
|
52
|
+
correct localization noise and the leading finite-time-step bias) and
|
|
53
|
+
parametric estimators (`infer_force` / `infer_diffusion`: noise-aware
|
|
54
|
+
likelihood fit, robust to localization error and coarse sampling,
|
|
55
|
+
accepts nonlinear models such as neural-network drifts).
|
|
56
|
+
- **Overdamped & underdamped inference** — works with position-only data;
|
|
57
|
+
velocities are reconstructed automatically for underdamped systems.
|
|
58
|
+
- **Composable state functions** — build force/diffusion models from
|
|
59
|
+
monomials, custom basis functions, pair interactions, or arbitrary
|
|
60
|
+
parametric families, all with automatic differentiation via JAX.
|
|
61
|
+
- **Sparse model selection** — Pareto-front beam search with AIC / BIC /
|
|
62
|
+
PASTIS information criteria.
|
|
63
|
+
- **Entropy production** — dissipation rate with error bar, for
|
|
64
|
+
overdamped and underdamped dynamics.
|
|
65
|
+
- **Simulation** — simulate Langevin SDEs from the same model objects
|
|
66
|
+
used for inference, including bootstrapped trajectories of a fitted model.
|
|
67
|
+
- **Trajectory toolkit** — mask-aware increments, synthetic degradation
|
|
68
|
+
(noise, downsampling, data loss, motion blur), streaming for large
|
|
69
|
+
datasets, I/O (CSV / Parquet / HDF5, tracking tables).
|
|
70
|
+
- **Diagnostics** — residual tests with action hints, an
|
|
71
|
+
overdamped-vs-underdamped classifier, predicted errors, comparison to
|
|
72
|
+
exact models.
|
|
73
|
+
|
|
74
|
+
## Installation
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pip install StochasticForceInference # import name: SFI
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
For development (editable install with test/doc dependencies):
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
git clone https://github.com/ronceray/StochasticForceInference.git
|
|
84
|
+
cd StochasticForceInference
|
|
85
|
+
pip install -e ".[dev,io]"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
> **Note:** SFI requires Python ≥ 3.11 and JAX ≥ 0.10.
|
|
89
|
+
|
|
90
|
+
## Quick start
|
|
91
|
+
|
|
92
|
+
For **experimental data**, load your trajectories and infer directly:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
import numpy as np
|
|
96
|
+
from SFI import OverdampedLangevinInference, TrajectoryCollection
|
|
97
|
+
from SFI.bases import monomials_up_to
|
|
98
|
+
|
|
99
|
+
# Load your tracked data (positions: T×d array, dt: time step)
|
|
100
|
+
positions = np.load("my_experiment.npz")["positions"] # shape (T, d)
|
|
101
|
+
coll = TrajectoryCollection.from_arrays(X=positions, dt=0.01)
|
|
102
|
+
|
|
103
|
+
# Infer using a polynomial basis — no model needed
|
|
104
|
+
B = monomials_up_to(order=3, dim=2, rank="vector")
|
|
105
|
+
inf = OverdampedLangevinInference(coll)
|
|
106
|
+
inf.infer_force_linear(B) # also estimates D and the measurement noise
|
|
107
|
+
inf.sparsify_force(criterion="PASTIS") # optional: find the minimal model
|
|
108
|
+
inf.compute_force_error()
|
|
109
|
+
inf.print_report() # coefficients with error bars
|
|
110
|
+
inf.diagnose().print_summary() # residual tests, with hints if one fails
|
|
111
|
+
|
|
112
|
+
# Coarsely sampled or very noisy recordings? Use the parametric estimator
|
|
113
|
+
# instead: inf.infer_force(B) — it models the measurement noise natively.
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
For a **synthetic example** (useful for validation):
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
import jax.numpy as jnp
|
|
120
|
+
from jax import random
|
|
121
|
+
|
|
122
|
+
from SFI import OverdampedLangevinInference
|
|
123
|
+
from SFI.bases import X, monomials_up_to
|
|
124
|
+
from SFI.langevin import OverdampedProcess
|
|
125
|
+
|
|
126
|
+
# 1. Build a force model (Ornstein–Uhlenbeck: F = -k x) and simulate a trajectory.
|
|
127
|
+
# X(dim) is the identity basis x ↦ x; theta_F holds its coefficient, so F(x) = -x.
|
|
128
|
+
proc = OverdampedProcess(F=X(dim=2), D=jnp.eye(2) * 0.5, theta_F=jnp.array([-1.0]))
|
|
129
|
+
proc.initialize(jnp.zeros(2))
|
|
130
|
+
coll = proc.simulate(dt=0.01, Nsteps=10_000, key=random.PRNGKey(0))
|
|
131
|
+
|
|
132
|
+
# 2. Infer from the trajectory using a generic polynomial basis
|
|
133
|
+
B = monomials_up_to(order=2, dim=2, rank="vector")
|
|
134
|
+
inf = OverdampedLangevinInference(coll)
|
|
135
|
+
inf.infer_force_linear(B)
|
|
136
|
+
inf.compute_force_error()
|
|
137
|
+
|
|
138
|
+
# 3. Inspect results and validate against the known model
|
|
139
|
+
inf.print_report()
|
|
140
|
+
inf.compare_to_exact(model_exact=proc)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Using SFI with an AI agent
|
|
144
|
+
|
|
145
|
+
SFI ships a workflow guide for AI coding agents (Claude Code, Codex,
|
|
146
|
+
Cursor, …) inside the package, matched to the installed version:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
python -m SFI guide # Markdown: workflow, decisions, pitfalls, API names
|
|
150
|
+
|
|
151
|
+
# Install it as an Agent Skill (path shown for Claude Code; other tools that support skills use their own folder)
|
|
152
|
+
mkdir -p ~/.claude/skills/stochastic-force-inference
|
|
153
|
+
python -m SFI guide --skill > ~/.claude/skills/stochastic-force-inference/SKILL.md
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The documentation has an [`llms.txt`](https://stochasticforceinference.readthedocs.io/llms.txt)
|
|
157
|
+
index. Agents that modify SFI itself should read
|
|
158
|
+
[`AGENTS.md`](https://github.com/ronceray/StochasticForceInference/blob/main/AGENTS.md).
|
|
159
|
+
|
|
160
|
+
**Coming from the original SFI scripts** (`StochasticForceInference.py`,
|
|
161
|
+
`StochasticTrajectoryData`, or the separate UnderdampedLangevinInference
|
|
162
|
+
package)? SFI 2 is a rewrite with a new API; the
|
|
163
|
+
[guide](https://github.com/ronceray/StochasticForceInference/blob/main/SFI/AGENT_GUIDE.md#9-coming-from-the-original-sfi-scripts-or-older-example-code)
|
|
164
|
+
maps the old calls to the new ones.
|
|
165
|
+
|
|
166
|
+
## Documentation
|
|
167
|
+
|
|
168
|
+
Full documentation is available at
|
|
169
|
+
[stochasticforceinference.readthedocs.io](https://stochasticforceinference.readthedocs.io), including:
|
|
170
|
+
|
|
171
|
+
- **[Start here](https://stochasticforceinference.readthedocs.io/en/latest/start_here.html)** — is SFI right for my data, and which route to take
|
|
172
|
+
- **[Tutorial](https://stochasticforceinference.readthedocs.io/en/latest/gallery/ou_demo.html)** — end-to-end walkthrough
|
|
173
|
+
- **[Examples gallery](https://stochasticforceinference.readthedocs.io/en/latest/gallery/index.html)** — worked examples covering sparsity, multi-particle, and SPDE inference
|
|
174
|
+
- **[Model building](https://stochasticforceinference.readthedocs.io/en/latest/statefunc/user_guide.html)** — composable state functions
|
|
175
|
+
- **[Trajectory handling](https://stochasticforceinference.readthedocs.io/en/latest/trajectory/user_guide.html)** — data ingestion, masking, degradation
|
|
176
|
+
- **[Running inference](https://stochasticforceinference.readthedocs.io/en/latest/inference/user_guide.html)** — estimator choice, overdamped/underdamped engines
|
|
177
|
+
- **[API reference](https://stochasticforceinference.readthedocs.io/en/latest/api_frontend.html)** — full autodoc
|
|
178
|
+
|
|
179
|
+
## Package structure
|
|
180
|
+
|
|
181
|
+
| Subpackage | Purpose |
|
|
182
|
+
| ----------------- | ---------------------------------------------------- |
|
|
183
|
+
| `SFI.statefunc` | Composable state functions: `Basis`, `PSF`, `SF` |
|
|
184
|
+
| `SFI.inference` | Overdamped & underdamped inference engines |
|
|
185
|
+
| `SFI.trajectory` | `TrajectoryCollection` / `TrajectoryDataset` |
|
|
186
|
+
| `SFI.langevin` | Langevin simulators (`OverdampedProcess`, …) |
|
|
187
|
+
| `SFI.bases` | Ready-made basis builders (monomials, pairs, SPDE, …) |
|
|
188
|
+
| `SFI.diagnostics` | Residual tests, dynamics classifier, error checks |
|
|
189
|
+
| `SFI.integrate` | Time-averaging integration engine |
|
|
190
|
+
| `SFI.utils` | Math helpers, formatting, plotting |
|
|
191
|
+
|
|
192
|
+
## Citation
|
|
193
|
+
|
|
194
|
+
If you use SFI, please cite the software (see [`CITATION.cff`](https://github.com/ronceray/StochasticForceInference/blob/main/CITATION.cff))
|
|
195
|
+
together with the method paper(s) relevant to the features you use.
|
|
196
|
+
|
|
197
|
+
The software is archived on Zenodo. Cite the concept DOI
|
|
198
|
+
[10.5281/zenodo.21532842](https://doi.org/10.5281/zenodo.21532842), which always
|
|
199
|
+
resolves to the latest release; each version also has its own DOI (v2.0.4:
|
|
200
|
+
[10.5281/zenodo.23498743](https://doi.org/10.5281/zenodo.23498743)).
|
|
201
|
+
|
|
202
|
+
See **[How to cite](https://stochasticforceinference.readthedocs.io/en/latest/#how-to-cite)** in the
|
|
203
|
+
documentation for the full, feature-specific list (overdamped, underdamped/ULI,
|
|
204
|
+
trapeze, and PASTIS references).
|
|
205
|
+
|
|
206
|
+
## Funding
|
|
207
|
+
|
|
208
|
+
Funded by the European Union (ERC, SuperStoc, 101117322). Views and opinions
|
|
209
|
+
expressed are however those of the author(s) only and do not necessarily
|
|
210
|
+
reflect those of the European Union or the European Research Council Executive
|
|
211
|
+
Agency. Neither the European Union nor the granting authority can be held
|
|
212
|
+
responsible for them. P. R. also acknowledges funding from the French National
|
|
213
|
+
Research Agency (ANR-16-CONV-0001) and from the Excellence Initiative of
|
|
214
|
+
Aix-Marseille University A\*MIDEX.
|
|
215
|
+
|
|
216
|
+
## License
|
|
217
|
+
|
|
218
|
+
MIT — see [LICENSE](https://github.com/ronceray/StochasticForceInference/blob/main/LICENSE) for details.
|