SFI.diagnostics.dynamics_order module¶
Overdamped-vs-underdamped dynamics classifier.
Reads raw trajectory data and decides whether the dynamics are overdamped
(OD, first-order Langevin) or underdamped (UD, second-order / inertial),
robust to high localization noise and coarse sampling. Entry point:
classify_dynamics().
The discriminator is the lag-resolved displacement covariance
C_k(dt) = <Delta x_t . Delta x_{t+k}> with Delta x_t = x_{t+1} - x_t:
White localization noise (variance
sigma^2per axis) contributes+2 sigma^2toC0,-sigma^2toC1and exactly 0 to ``C_{k>=2}`` — so lag >= 2 is measurement-noise-immune by construction.A force field cannot fake inertia: for OD the apparent kinetic energy
C0/dt^2diverges as2D/dtwhile the lag-2 velocity correlation stays finite, so the noise-corrected ratiorho2 = C2 / (C0 + 2 C1)(the combinationC0 + 2 C1cancels white localization noise exactly) tends to 0; for UD the displacement is ballistic (Delta x ~ v dt) sorho2rises to a positive plateau. Scanningdt(viaTrajectoryCollection.degrade()) removes the force confound; using lag 2 removes the noise.
The pipeline (see classify_dynamics()) layers a model-free
dt-scaling test (_scaling_statistics()), a parametric covariance fit
(_fit_dynamics()) and an overdamped-fit residual-autocorrelation
cross-check (_cross_check()) into an OD / UD / inconclusive verdict.
- class SFI.diagnostics.dynamics_order.DynamicsOrderReport(verdict, fit=<factory>, scaling=<factory>, scan=<factory>, cross_check=None, meta=<factory>)[source]¶
Bases:
objectResult of
classify_dynamics().- Variables:
verdict (str) –
"OD","UD"or"inconclusive".fit (dict) – Parametric fit output (
params=sigma2, D, V, gamma,tau_v,stderr,V_z,delta_aiccand the raw SSR / AICc values).scaling (dict) – Model-free statistics (
rho2,K,beta).scan (dict) – Lag-0/1/2 covariances across the dt scan (
strides,dt,C0,C1,C2,n_eff).cross_check (dict or None) – Overdamped-fit Ljung–Box result, or
Noneif disabled.meta (dict) – Sampling summary (
d,n_datasets,strides,dt_min/max,gamma_dt_min).
- Parameters:
verdict (str)
fit (dict)
scaling (dict)
scan (dict)
cross_check (dict | None)
meta (dict)
- cross_check: dict | None = None¶
- fit: dict¶
- meta: dict¶
- scaling: dict¶
- scan: dict¶
- verdict: str¶
- SFI.diagnostics.dynamics_order.classify_dynamics(data, *, strides=None, cross_check=True)[source]¶
Classify trajectory data as overdamped, underdamped, or inconclusive.
Robust to high localization noise (lag >= 2 covariances are noise-immune) and reports inconclusive at coarse sampling where the momentum is unresolved (
gamma * dt >~ 1), rather than guessing.- Parameters:
data (TrajectoryCollection) – Raw trajectories (positions). Velocities are not required — the test reconstructs the dynamics order from position increments alone.
strides (sequence of int, optional) – Coarse-graining factors for the dt scan. Default: a geometric set
1, 2, 4, ...capped so the coarsest still has enough samples.cross_check (bool) – Run the Layer-3 overdamped-fit residual-autocorrelation corroboration (default
True).
- Return type:
Notes
Assumes white localization noise; spatially uniform, isotropic pooling of components. Strong memory (a generalized Langevin / viscoelastic bath) can also produce velocity persistence without inertia — out of scope; the test detects trajectory smoothness, which inertia produces.
Examples
>>> report = classify_dynamics(collection) >>> report.verdict 'UD'