dysts API Reference¶
The API reference for the dysts repository: https://github.com/williamgilpin/dysts
Base Classes¶
Dynamical systems in Python
- class dysts.base.BaseDyn(metadata_path: str | None = None, metadata: dict[str, Any] | None = None, required_fields: tuple[str | tuple[str, ...], ...] = ('parameters', ('dimension', 'embedding_dimension')), **extra_metadata)¶
A base class for dynamical systems
- has_jacobian() bool ¶
Check if the subclass has implemented the _jac method.
- static load_system_metadata(system_name: str, data_path: str) dict[str, Any] ¶
Load data from a JSON file
Returns None if the system name is not found
- static load_trajectory(data_path: str, system_name: str, return_times=False, standardize=False)¶
Load a precomputed trajectory for the dynamical system
- Parameters:
data_path (str) – Path to the data file, of format {name}.json.gz
standardize (bool) – Standardize the output time series.
return_times (bool) – Whether to return the timepoints at which the solution was computed
- Returns:
A T x D trajectory tpts, sol (ndarray): T x 1 timepoint array, and T x D trajectory
- Return type:
sol (ndarray)
- make_trajectory(*args, **kwargs)¶
Make a trajectory for the dynamical system
- transform_ic(transform_fn: Callable[[ndarray, Any], ndarray | None]) bool ¶
Updates the initial condition via a transform function
- transform_params(transform_fn: Callable[[str, ndarray, Any], ndarray | None]) bool ¶
Updates the current parameter list via a transform function
- class dysts.base.DynMap(metadata_path: str = '/Users/william/program_repos/dysts/data/discrete_maps.json', parameters: dict[str, Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]] | None = None, **kwargs)¶
A discrete map dynamical system class
- make_trajectory(n: int, init_cond: ndarray | None = None, inverse: bool = False, return_times: bool = False, standardize: bool = False, **kwargs) ndarray | tuple[ndarray, ndarray] ¶
Generate a fixed-length trajectory with default parameters and initial condition(s).
- Parameters:
n (int) – The length of each trajectory.
init_cond (Optional[np.ndarray]) – Initial conditions. If None, use default.
inverse (bool) – Whether to reverse the trajectory.
return_times (bool) – Whether to return the timepoints of the solution.
standardize (bool) – Whether to standardize the output time series.
- Returns:
If return_times is False, returns the trajectory. If return_times is True, returns a tuple of (timepoints, trajectory).
- Return type:
Union[np.ndarray, Tuple[np.ndarray, np.ndarray]]
- rhs(X)¶
The right hand side of a dynamical map
- rhs_inv(Xp)¶
The inverse of the right hand side of a dynamical map
- class dysts.base.DynSys(metadata_path: str | None = '/Users/william/program_repos/dysts/data/chaotic_attractors.json', parameters: dict[str, Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]] | None = None, dt: float | None = None, period: float | None = None, maximum_lyapunov_estimated: float | None = None, **kwargs: Any)¶
A continuous dynamical system base class
- jac(X, t)¶
The Jacobian of the dynamical system
- make_trajectory(n: int, dt: float = 0.001, init_cond: ndarray | None = None, resample: bool = True, pts_per_period: int = 100, return_times: bool = False, standardize: bool = False, postprocess: bool = True, noise: float = 0.0, timescale: str = 'Fourier', method: str = 'Radau', random_seed: int = 0, rtol: float = 1e-12, atol: float = 1e-12, verbose: bool = False, **kwargs) ndarray | tuple[ndarray, ndarray] | None | tuple[None, None] ¶
Generate a fixed-length trajectory for the dynamical system.
- Parameters:
n – Total number of trajectory points.
dt – Time step for integration. Defaults to 1e-3 or system’s default if set.
init_cond – Initial conditions. If None, uses system’s default.
resample – Whether to resample trajectory to match dominant Fourier components.
pts_per_period – Number of points per period if resampling.
return_times – If True, return time points along with trajectory.
standardize – If True, standardize the output time series.
postprocess – If True, apply coordinate conversions and rescalings.
noise – Stochasticity level in integrated dynamics (corresponds to Brownian motion).
timescale – Timescale for resampling. “Fourier” (default) or “Lyapunov”.
method – Integration method.
random_seed – Seed for random number generation.
rtol – Relative tolerance for integration.
atol – Absolute tolerance for integration.
verbose – Whether to trigger warnings.
**kwargs – Additional arguments for integration routine.
- Returns:
np.ndarray: T x D trajectory array. If return_times is True:
Tuple[np.ndarray, np.ndarray]: T x 1 time point array and T x D trajectory array.
None: If no complete trajectories are found.
- Return type:
If return_times is False
- Raises:
ValueError – If an invalid timescale is provided.
- rhs(X, t)¶
The right hand side of a dynamical equation
- class dysts.base.DynSysDelay(metadata_path: str = '/Users/william/program_repos/dysts/data/chaotic_attractors.json', dt: float | None = None, period: float | None = None, maximum_lyapunov_estimated: float | None = None, tau: float | None = None, parameters: dict[str, float | int | Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]] | None = None, **kwargs)¶
A delayed differential equation object. Uses a exposed fork of ddeint The delay timescale is assumed to be the “tau” field. The embedding dimensions are set to a default value, but delay equations are infinite dimensional.
- delayed_rhs(X: Callable[[float], Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]], t: float, tau: float) Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes] ¶
The right hand side of a dynamical equation
- make_trajectory(n: int, init_cond: ndarray | None = None, dt: float = 0.001, tau: float = 1, resample: bool = True, pts_per_period: int = 100, standardize: bool = False, timescale: str = 'Fourier', return_times: bool = False, embedding_dim: int | None = None, history_function: Callable[[float], Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]] | None = None, random_seed: int = 0, **kwargs)¶
Generate a fixed-length trajectory with default timestep, parameters, and initial conditions.
- Parameters:
n (int) – the total number of trajectory points
method (str) – Not used. Currently Euler is the only option here
noise (float) – The amplitude of brownian forcing
resample (bool) – whether to resample trajectories to have matching dominant Fourier components
pts_per_period (int) – if resampling, the number of points per period
standardize (bool) – Standardize the output time series.
timescale (str) – The timescale to use for resampling. “Fourier” (default) uses the dominant significant Fourier timescale, estimated using the periodogram of the system and surrogates. “Lyapunov” uses the Lypunov timescale of the system.
return_times (bool) – Whether to return the timepoints at which the solution was computed
postprocess (bool) – Whether to apply coordinate conversions and other domain-specific rescalings to the integration coordinates
embedding_dim (int) – Optionally augment solution with delay embedded trajectories. If equation is multi-dimensional with dimension d, then this will return a flattened delay embedding of shape (n, d*embedding_dim) where each consecutive (n, d) block will be a trajectory for a different delay parameter.
history_function (callable) – Function for specifying past conditions i.e. points for t < 0
- dysts.base.staticjit(func: Callable) Callable ¶
Decorator to apply numba’s njit decorator to a static method
Utilities¶
Helper utilities for working with time series arrays. This module is intended to have no dependencies on the rest of the package.
- dysts.utils.utils.cartesian_to_polar(x, y)¶
Convert 2D cartesian coordinates to polar coordinates
- dysts.utils.utils.find_characteristic_timescale(y, k=1, window=True)¶
Find the k leading characteristic timescales in a time series using the power spectrum..
- dysts.utils.utils.find_psd(y, window=True)¶
Find the power spectrum of a signal
- dysts.utils.utils.find_significant_frequencies(sig, window=True, fs=1, n_samples=100, significance_threshold=0.95, surrogate_method='rp', show=False, return_amplitudes=False)¶
Find power spectral frequencies that are significant in a signal, by comparing the appearance of a peak with its appearance in randomly-shuffled surrogates.
If no significant freqencies are detected, the significance floor is lowered
- Parameters:
window (bool) – Whether to window the signal before taking the FFT
thresh (float) – The number of standard deviations above mean to be significant
fs (int) – the sampling frequency
n_samples (int) – the number of surrogates to create
show (bool) – whether to show the psd of the signal and the surrogate
- Returns:
The frequencies overrated in the dataset amps (ndarray): the amplitudes of the PSD at the identified frequencies
- Return type:
freqs (ndarray)
- dysts.utils.utils.find_slope(x, y)¶
Given two vectors or arrays, compute the best fit slope using an analytic formula. For arrays is computed along the last axis.
- Parameters:
x (ndarray) – (N,) or (M, N)
y (ndarray) – (N,) or (M, N)
- Returns:
the values of the slope for each of the last dimensions
- Return type:
b (ndarray)
- dysts.utils.utils.freq_from_autocorr(sig, fs=1)¶
Estimate frequency using autocorrelation
- Parameters:
sig (ndarray) – A univariate signal
fs (int) – The sampling frequency
- Returns:
The dominant frequency
- Return type:
out (float)
References
Modified from the following https://gist.github.com/endolith/255291
- dysts.utils.utils.freq_from_fft(sig, fs=1)¶
Estimate frequency of a signal from the peak of the power spectrum
- Parameters:
sig (ndarray) – A univariate signal
fs (int) – The sampling frequency
- Returns:
The dominant frequency
- Return type:
out (float)
References
Modified from the following https://gist.github.com/endolith/255291
- dysts.utils.utils.jac_fd(func0, y0, eps=0.001, m=1, method='central', verbose=False)¶
Calculate numerical jacobian of a function with respect to a reference value
- Parameters:
func (callable) – a vector-valued function
y0 (ndarray) – a point around which to take the gradient
eps (float) – the step size for the finite difference calculation
- Returns:
a numerical estimate of the Jacobian about that point
- Return type:
jac (ndarray)
- dysts.utils.utils.logarithmic_n(min_n, max_n, factor)¶
Return a list of values by successively multiplying a minimum value min_n by a factor > 1 until a maximum value max_n is reached. Non-integer results are rounded down. Based on a similar function in the nolds Python library.
- Parameters:
min_n (float) – minimum value (must be < max_n)
max_n (float) – maximum value (must be > min_n)
factor (float) – factor used to increase min_n (must be > 1)
- Returns:
min_n, min_n * factor, min_n * factor^2, … min_n * factor^i < max_n without duplicates
- Return type:
list of integers
- dysts.utils.utils.make_epsilon_ball(pt, n, eps=1e-05, random_state=None)¶
Uniformly sample a fixed-radius ball of points around a given point via using Muller’s method
- Parameters:
pt (ndarray) – The center of the sampling
n (int) – The number of points to sample
eps (float) – The radius of the ball
random_state (int) – Initialize the random number generator
- Returns:
The set of randomly-sampled points
- Return type:
out (ndarray)
- dysts.utils.utils.make_surrogate(data, method='rp')¶
- Parameters:
data (ndarray) – A one-dimensional time series
method (str) – “rs” or rp”
- Returns:
A single random surrogate time series
- Return type:
surr_data (ndarray)
- dysts.utils.utils.min_data_points_rosenstein(emb_dim, lag, trajectory_len, min_tsep)¶
Adapted from the nolds Python library: https://github.com/CSchoel/nolds/blob/master/nolds/measures.py
Helper function that calculates the minimum number of data points required to use lyap_r. Note that none of the required parameters may be set to None. :param emb_dim: Embedding dimension :type emb_dim: int :param lag: Lag between time series values :type lag: int :param trajectory_len: Length of trajectory to follow :type trajectory_len: int :param min_tsep: Minimum temporal separation :type min_tsep: int
- Returns:
minimum number of data points required to call lyap_r with the given parameters
- Return type:
int
- dysts.utils.utils.nan_fill(a, axis=0, mode='forward')¶
Fill NaN values in an array using a specified method
- Parameters:
a (np.ndarray) – the array to fill
axis (int) – the axis along which to fill NaN values
mode (str) – the method to use for filling NaN values
- Returns:
the array with NaN values filled
- Return type:
a_filled (np.ndarray)
- dysts.utils.utils.nanmean_trimmed(arr, percentile=0.5, axis=None)¶
Compute the trimmed mean of an array along a specified axis, ignoring NaNs.
- Parameters:
arr (np.array) – Input array
percentile (float) – The fraction of data to be trimmed. Should be between 0 and 1. Default is 0.5.
axis (int) – Axis along which to compute the trimmed mean. If None (the default), compute over the whole array.
- Returns:
Trimmed mean of the input array along the specified axis.
- dysts.utils.utils.pad_axis(arr, d, axis=-1, padding=0)¶
Pad axis of arr with a constant padding to a desired shape
- dysts.utils.utils.pad_to_shape(arr, target_shape)¶
Given an array, and a target shape, pad the dimensions in order to reach the desired shape Currently, if the rank of the array is lower than the target shape, singleton dimensions are appended to the rank
- Parameters:
arr (ndarray) – The array to pad.
target_shape (iterable) – The desired shape.
- Returns:
The padded array,
- Return type:
arr (ndarray)
- dysts.utils.utils.polar_to_cartesian(r, th)¶
Convert polar coordinates to 2D Cartesian coordinates
- dysts.utils.utils.rowwise_euclidean(x, y)¶
Computes the euclidean distance across rows
- dysts.utils.utils.standardize_ts(a, scale=1.0)¶
Standardize an array along dimension -2 For dimensions with zero variance, divide by one instead of zero
- Parameters:
a (ndarray) – a matrix containing a time series or batch of time series with shape (T, D) or (B, T, D)
scale (float) – the number of standard deviations by which to scale
- Returns:
- A standardized time series with the same shape as
the input
- Return type:
ts_scaled (ndarray)
Native python utilities
- class dysts.utils.native_utils.ComputationHolder(func, *args, timeout: float = 10, **kwargs)¶
A wrapper class to force a computation to stop after a timeout.
- Parameters
func (callable): the function to run args (tuple): the arguments to pass to the function kwargs (dict): the keyword arguments to pass to the function timeout (int): the timeout in seconds. If None is passed, the computation
will run indefinitely until it finishes.
- Example
>>> def my_func(): ... while True: ... print("hello") ... time.sleep(8) >>> ch = ComputationHolder(my_func, timeout=3) >>> ch.run() hello hello hello None
- dysts.utils.native_utils.convert_json_to_gzip(fpath, encoding='utf-8', delete_original=False)¶
Convert a json file to a gzip file in a format that can be easily read by the dysts package. By default, the gzip file will be saved with the same name and in the same directory as the json file, but with a “.gz” extension.
- Parameters:
fpath (str) – Path to the json file to be converted
encoding (str) – Encoding to use when writing the gzip file
delete_original (bool) – Whether to delete the original json file after conversion. Default is False.
- Returns:
None
- dysts.utils.native_utils.has_module(module_name: str) bool ¶
Check if a module is installed
- dysts.utils.native_utils.num_unspecified_params(func) int ¶
Count required parameters that haven’t been specified through partial or defaults.
- Parameters:
func – Function or partial function to inspect
- Returns:
Number of parameters that must be specified when calling the function
Utilities for integration
- class dysts.utils.integration_utils.dde(f, jac=None)¶
This class overwrites a few functions of
scipy.integrate.ode
to allow for updates of the pseudo-variable Y between each integration step.- integrate(t, step=False, relax=False)¶
Find y=y(t), set y as an initial condition, and return y.
- Parameters:
t (float) – The endpoint of the integration step.
step (bool) – If True, and if the integrator supports the step method, then perform a single integration step and return. This parameter is provided in order to expose internals of the implementation, and should not be changed from its default value in most cases.
relax (bool) – If True and if the integrator supports the run_relax method, then integrate until t_1 >= t and return.
relax
is not referenced ifstep=True
. This parameter is provided in order to expose internals of the implementation, and should not be changed from its default value in most cases.
- Returns:
y – The integrated value at t
- Return type:
float
- set_initial_value(Y)¶
Set initial conditions y(t) = y.
- class dysts.utils.integration_utils.ddeVar(g, tc=0)¶
The instances of this class are special function-like variables which store their past values in an interpolator and can be called for any past time: Y(t), Y(t-d). Very convenient for the integration of DDEs.
- update(t, Y)¶
Add one new (ti,yi) to the interpolator
- dysts.utils.integration_utils.ddeint(func, g, tt, fargs=None)¶
Solves Delay Differential Equations
Similar to scipy.integrate.odeint. Solves a Delay differential Equation system (DDE) defined by
Y(t) = g(t) for t<0 Y’(t) = func(Y,t) for t>= 0
Where func can involve past values of Y, like Y(t-d).
- Parameters:
func – a function Y,t,args -> Y’(t), where args is optional. The variable Y is an instance of class ddeVar, which means that it is called like a function: Y(t), Y(t-d), etc. Y(t) returns either a number or a numpy array (for multivariate systems).
g – The ‘history function’. A function g(t)=Y(t) for t<0, g(t) returns either a number or a numpy array (for multivariate systems).
tt – The vector of times [t0, t1, …] at which the system must be solved.
fargs – Additional arguments to be passed to parameter
func
, if any.
Examples
We will solve the delayed Lotka-Volterra system defined as
For t < 0: x(t) = 1+t y(t) = 2-t
For t >= 0: dx/dt = 0.5* ( 1- y(t-d) ) dy/dt = -0.5* ( 1- x(t-d) )
The delay
d
is a tunable parameter of the model.import numpy as np from ddeint import ddeint def model(XY,t,d): x, y = XY(t) xd, yd = XY(t-d) return np.array([0.5*x*(1-yd), -0.5*y*(1-xd)]) g = lambda t : np.array([1+t,2-t]) # 'history' at t<0 tt = np.linspace(0,30,20000) # times for integration d = 0.5 # set parameter d yy = ddeint(model,g,tt,fargs=(d,)) # solve the DDE !
- dysts.utils.integration_utils.generate_ic_ensemble(model, tpts0, n_samples, frac_perturb_param=0.1, frac_transient=0.1, ic_range=None, random_state=0)¶
Generate an ensemble of trajectories with random initial conditions, labelled by different initial conditions
- Parameters:
model (callable_) – function defining the numerical derivative
tpts (ndarray) – the timesteps over which to run the simulation
n_samples (int) – the number of different initial conditons
frac_perturb_param (float) – the amount to perturb the ic by
frac_transient (float) – the fraction of time for the time series to settle onto the attractor
ic_range (list) – a starting value for the initial conditions
random_state (int) – the seed for the random number generator
- Returns:
A set of initial conditions
- Return type:
all_samples (array)
- dysts.utils.integration_utils.integrate_dyn(f: Callable, ic: ndarray, tvals: ndarray, noise: float | ndarray = 0.0, dtval=None, **kwargs)¶
Given the RHS of a dynamical system, integrate the system noise > 0 requires the Python library sdeint (assumes Brownian noise)
- Parameters:
f (callable) – The right hand side of a system of ODEs.
ic (ndarray) – the initial conditions
tvals (ndarray) – times points at which to evaluate the solution
noise (float or iterable) – The amplitude of the Langevin forcing term. If a vector is passed, this will be different for each dynamical variable
dtval (float) – The starting integration timestep. This will be the exact timestep for fixed-step integrators, or stochastic integration.
kwargs (dict) – Arguments passed to scipy.integrate.solve_ivp.
- Returns:
The integrated trajectory
- Return type:
sol (ndarray)
- dysts.utils.integration_utils.integrate_weiner(f, noise_amp, ic, tvals)¶
Given the RHS of a dynamical system, integrate the system assuming Brownian noise Requires the Python library sdeint
- Parameters:
f (callable) – the right hand side of a system of ODE
noise_amp (float) – the amplitude of the Langevin forcing term
- dysts.utils.integration_utils.resample_timepoints(model, ic, tpts, cutoff=10000, pts_per_period=100)¶
Given a differential equation, initial condition, and a set of integration points, determine a new set of timepoints that scales to the periodicity of the model
- Parameters:
model (callable) – the right hand side of a set of ODEs
ic (list) – the initial conditions
tpts (array) – the timepoints over which to integrate
pts_per_period (int) – the number of timepoints to sample in each period
- Returns:
The resampled timepoints
- Return type:
new_timepoints (ndarray)
Analysis¶
Functions that act on DynSys or DynMap objects
- dysts.analysis.calculate_lyapunov_exponent(traj1, traj2, dt=1.0)¶
Calculate the lyapunov exponent of two multidimensional trajectories using simple linear regression based on the log-transformed separation of the trajectories.
- Parameters:
traj1 (np.ndarray) – trajectory 1 with shape (n_timesteps, n_dimensions)
traj2 (np.ndarray) – trajectory 2 with shape (n_timesteps, n_dimensions)
dt (float) – time step between timesteps
- Returns:
lyapunov exponent
- Return type:
float
- dysts.analysis.compute_timestep(system: DynSys, total_length: int = 40000, transient_fraction: float = 0.2, num_iters: int = 20, pts_per_period: int = 1000, timescale: str = 'Fourier') tuple[ndarray, ndarray] ¶
Given a dynamical system object, find the integration timestep based on the largest signficant frequency
- Parameters:
model (DynSys) – A dynamical systems object.
total_length (int) – The total trajectory length to use to determine timescales.
transient_fraction (float) – The fraction of a trajectory to discard as transient
num_iters (int) – The number of refinements to the timestep
pts_per_period (int) – The target integration timestep relative to the signal.
visualize (bool) – Whether to plot timestep versus time, in order to identify problems with the procedure
- Returns
dt (float): The best integration timestep period (float, optional): The dominant timescale in the signal
- dysts.analysis.corr_gpdim(traj1, traj2, register=False, standardize=False, **kwargs)¶
Given two multivariate time series, estimate their similarity using the cross Grassberger-Procaccia dimension
This quantity is defined as the cross-correlation between the two time series normalized by the product of the Grassberger-Procaccia dimension of each time series. np.sqrt(<ox oy> / ox oy)
- Parameters:
traj1 (np.array) – T x D, where T is the number of timepoints, and D is the number of dimensions
traj2 (np.array) – T x D, where T is the number of timepoints, and D is the number of dimensions
register (bool) – Whether to register the two time series before computing the cross-correlation
standardize (bool) – Whether to standardize the time series before computing the cross-correlation
- Returns:
The cross-correlation between the two time series
- Return type:
float
- dysts.analysis.estimate_powerlaw(data0)¶
Given a 1D array of continuous-valued data, estimate the power law exponent using the maximum likelihood estimator proposed by Clauset, Shalizi, Newman (2009).
- Parameters:
data0 (np.ndarray) – An array of continuous-valued data
- Returns:
The estimated power law exponent
- Return type:
float
- dysts.analysis.find_lyapunov_exponents(model, traj_length, pts_per_period=500, tol=1e-08, min_tpts=10, **kwargs)¶
Given a dynamical system, compute its spectrum of Lyapunov exponents. :param model: the right hand side of a differential equation, in format
func(X, t)
- Parameters:
traj_length (int) – the length of each trajectory used to calulate Lyapunov exponents
pts_per_period (int) – the sampling density of the trajectory
kwargs – additional keyword arguments to pass to the model’s make_trajectory method
- Returns:
A list of computed Lyapunov exponents
- Return type:
final_lyap (ndarray)
References
- Christiansen & Rugh (1997). Computing Lyapunov spectra with continuous
Gram-Schmidt orthonormalization
Example
>>> import dysts >>> model = dysts.Lorenz() >>> lyap = dysts.find_lyapunov_exponents(model, 1000, pts_per_period=1000) >>> print(lyap)
- dysts.analysis.gp_dim(data, y_data=None, rvals=None, nmax=100)¶
Estimate the Grassberger-Procaccia dimension for a numpy array using the empirical correlation integral.
- Parameters:
data (np.array) – T x D, where T is the number of datapoints/timepoints, and D is the number of features/dimensions
y_data (np.array, Optional) – A second dataset of shape T2 x D, for computing cross-correlation.
rvals (np.array) – A list of radii
nmax (int) – The number of points at which to evaluate the correlation integral
- Returns:
- The discrete bins at which the correlation integral is
estimated
corr_sum (np.array): The estimates of the correlation integral at each bin
- Return type:
rvals (np.array)
- dysts.analysis.gpdistance(traj1, traj2, standardize=True, register=False, **kwargs)¶
Given two multivariate time series, estimate their similarity using the cross Grassberger-Procaccia distance
- Parameters:
traj1 (np.array) – T x D, where T is the number of timepoints, and D is the number of dimensions
traj2 (np.array) – T x D, where T is the number of timepoints, and D is the number of dimensions
register (bool) – Whether to register the two time series before computing the cross-correlation
standardize (bool) – Whether to standardize the time series before computing the cross-correlation
- dysts.analysis.kaplan_yorke_dimension(spectrum0)¶
Calculate the Kaplan-Yorke dimension, given a list of Lyapunov exponents
- dysts.analysis.logarithmic_n(min_n, max_n, factor)¶
Return a list of values by successively multiplying a minimum value min_n by a factor > 1 until a maximum value max_n is reached. Non-integer results are rounded down. Based on a similar function in the nolds Python library.
- Parameters:
min_n (float) – minimum value (must be < max_n)
max_n (float) – maximum value (must be > min_n)
factor (float) – factor used to increase min_n (must be > 1)
- Returns:
min_n, min_n * factor, min_n * factor^2, … min_n * factor^i < max_n without duplicates
- Return type:
list of integers
- dysts.analysis.max_lyapunov_exponent(eq: DynSys, max_walltime: float, rtol: float = 0.001, atol: float = 1e-10, n_samples: int = 1000, traj_length: int = 5000, **kwargs)¶
Calculate the lyapunov spectrum of the system using a naive method based on the log-transformed separation of the trajectories over time.
- Parameters:
eq (dysts.DynSys) – equation to calculate the lyapunov spectrum of
rtol (float) – relative tolerance for the separation of the trajectories
atol (float) – absolute tolerance for the separation of the trajectories
n_samples (int) – number of initial conditions to sample
traj_length (int) – length of the trajectories to sample. This should be long enough to ensure that most trajectories explore the attractor.
max_walltime (float) – maximum walltime in seconds to spend on the calculation of a given trajectory. If the calculation takes longer than this, the trajectory is discarded and a new one is sampled.
**kwargs – keyword arguments to pass to the sample / make_trajectory method of the dynamical equation
- Returns:
largest lyapunov exponent
- Return type:
float
Example
>>> import dysts >>> eq = dysts.Lorenz() >>> max_lyap = dysts.lyapunov_exponent_naive(eq)
- dysts.analysis.rowwise_euclidean(x, y)¶
Computes the euclidean distance across rows
- dysts.analysis.sample_initial_conditions(model, points_to_sample, traj_length=1000, pts_per_period=30)¶
Generate a random sample of initial conditions from a dynamical system
- Parameters:
model (callable) – the right hand side of a differential equation, in format func(X, t)
points_to_sample (int) – the number of random initial conditions to sample
traj_length (int) – the total length of the reference trajectory from which points are drawn
pts_per_period (int) – the sampling density of the trajectory
- Returns:
The points with shape (points_to_sample, d)
- Return type:
sample_points (ndarray)
Systems¶
Utilities for the implemented systems
- dysts.systems.compute_trajectory_statistics(n: int, subset: Sequence[str], datapath: PathLike | None = None, **kwargs) dict[str, dict[str, ndarray[tuple[int, ...], dtype[float64]]]] ¶
Compute mean and std for given trajectory list :param n: The number of timepoints to integrate :type n: int :param subset: A list of system names. Defaults to all continuous systems.
Can also pass in sys_class as a kwarg to specify other system classes.
- Parameters:
datapath (str) – Path to save the computed statistics to a JSON file
kwargs – Additional keyword arguments passed to the integration routine
- dysts.systems.get_attractor_list(sys_class: str = 'continuous', exclude: list[str] = []) list[str] ¶
Get names of implemented dynamical systems
- Parameters:
sys_class – class of systems to get the name of - must be one of [‘continuous’, ‘continuous_no_delay’, ‘delay’, ‘discrete’]
exclude – list of systems to exclude, optional
- Returns:
Sorted list of systems belonging to sys_class
- dysts.systems.get_system_data(sys_class: str = 'continuous', exclude: list[str] = []) dict[str, Any] ¶
Get system data from the dedicated system class json files
- Parameters:
sys_class – class of systems to get the name of - must be one of [‘continuous’, ‘continuous_no_delay’, ‘delay’, ‘discrete’]
exclude – list of systems to exclude, optional
- Returns:
Data from json file filtered by sys_class as a dict
- dysts.systems.make_trajectory_ensemble(n: int, use_tqdm: bool = True, use_multiprocessing: bool = False, subset: Sequence[str] | Sequence[BaseDyn] | None = None, event_fns: Sequence[Callable] | None = None, silent_errors: bool = False, **kwargs) dict[str, ndarray[tuple[int, ...], dtype[float64]] | None] ¶
Integrate multiple dynamical systems with identical settings
- Parameters:
n (int) – The number of timepoints to integrate
use_tqdm (bool) – Whether to use a progress bar
use_multiprocessing (bool) – Not yet implemented.
subset (list) – A list of system names or BaseDyn (e.g. custom dynamical systems). Defaults to all continuous systems. Can also pass in sys_class as a kwarg to specify other system classes.
event_fns (list) –
- A list of functions that can take the signatures:
(system: BaseDyn) -> (event_fn: Callable[[float, Array], float])
(event_fn: Callable[[float, Array], float])
() -> (event_fn: Callable[[float, Array], float])
If multiprocessing is used, the event functions must be of type 1 or 3 to avoid state persistence across processes.
silent_errors (bool) – Whether to fail silently if an error occurs
kwargs (dict) – Integration options passed to each system’s make_trajectory() method
- Returns:
A dictionary containing trajectories for each system
- Return type:
all_sols (dict)
Sampling¶
Example sampling functions for dysts
- class dysts.sampling.BaseSampler(random_seed: int = 0)¶
Base class for any sampling-based transformations
- set_rng(rng: Generator) None ¶
Required for multiprocessing
- class dysts.sampling.GaussianInitialConditionSampler(random_seed: int = 0, scale: float = 0.0001, verbose: bool = False)¶
Sample gaussian perturbations for each initial condition in a given system list
- class dysts.sampling.SignedGaussianParamSampler(random_seed: int = 0, scale: float = 0.01, verbose: bool = False)¶
Sample gaussian perturbations for system parameters
Note
This is a MWE of a parameter transform
Other parameter transforms should follow this dataclass template
- Parameters:
random_seed – for random sampling
scale – std (isotropic) of gaussian used for sampling
- class dysts.sampling.OnAttractorInitCondSampler(random_seed: int = 0, reference_traj_length: int = 4096, reference_traj_transient: int = 500, trajectory_cache: dict[str, ~numpy.ndarray[tuple[int, ...], ~numpy.dtype[~numpy.float64]]] = <factory>, verbose: bool = False, events: list[~typing.Callable] | None = None)¶
Sample points from the attractor of a system
- Subtleties:
This is slow, it requires integrating each system with its default parameters before sampling from the attractor.
The sampled initial conditions from this sampler are necessarily tied to the attractor defined by the default parameters.
- Parameters:
reference_traj_length – Length of the reference trajectory to use for sampling ic on attractor.
reference_traj_transient – Transient length to ignore for the reference trajectory
trajectory_cache – Cache of reference trajectories for each system.
events – events to pass to solve_ivp
Metrics¶
Metrics for comparing two time series. These metrics are included to faciliate benchmarking of the algorithms in this package while reducing dependencies.
For more exhaustive sets of metrics, use the external tslearn, darts, or sktime libraries.
- class dysts.metrics.GaussianMixture(means, covariances, weights=None)¶
A Gaussian Mixture Model class.
- Parameters:
means (list) – A list of means for each component of the GMM.
covariances (list) – A list of covariance matrices for each component of the GMM.
weights (list) – A list of weights for each component of the GMM.
- means¶
An array of means for each component of the GMM.
- Type:
np.ndarray
- covariances¶
An array of covariance matrices for each component of the GMM.
- Type:
np.ndarray
- weights¶
An array of weights for each component of the GMM.
- Type:
np.ndarray
- n_components¶
The number of components in the GMM.
- Type:
int
- gaussians¶
A list of multivariate_normal objects, one for each component
- Type:
list
- sample(n_samples=1)¶
Draw samples from the Gaussian Mixture Model.
- Parameters:
n_samples (int) – The number of samples to draw.
- Returns:
An array of shape (n_samples, ndim) containing the drawn samples.
- Return type:
samples (np.ndarray)
- dysts.metrics.are_broadcastable(shape1: tuple[int, ...], shape2: tuple[int, ...]) bool ¶
Check if two numpy arrays are broadcastable.
- Parameters:
shape1 (tuple[int, ...]) – The shape of the first array
shape2 (tuple[int, ...]) – The shape of the second array
- Returns:
True if the arrays are broadcastable, False otherwise
- Return type:
bool
Examples
>>> are_broadcastable((1, 2, 3), (4, 5, 6)) False >>> are_broadcastable((1, 2, 3), (3,)) True
- dysts.metrics.average_hellinger_distance(ts_true: ndarray, ts_gen: ndarray, num_freq_bins: int = 100) float ¶
Compute the average Hellinger distance between power spectra of two multivariate time series.
- Parameters:
ts_true (np.ndarray) – True time series, shape (n_samples, n_dimensions).
ts_gen (np.ndarray) – Generated time series, shape (n_samples, n_dimensions).
num_freq_bins (int) – Number of frequency bins to use in FFT for power spectrum.
- Returns:
Average Hellinger distance across all dimensions.
- Return type:
avg_dh
References
- Mikhaeil et al. Advances in Neural Information Processing Systems, 35:
11297–11312, December 2022.
- dysts.metrics.calculate_season_error(y_past, m, time_dim=-1)¶
Calculate the mean absolute error between the forward and backward slices of the past data.
- Parameters:
y_past (np.ndarray) – The past data
m (int) – The season length
time_dim (int) – The dimension of the time series
- Returns:
The mean absolute error
- Return type:
float
Examples
>>> calculate_season_error(y_past, m)
- dysts.metrics.coefficient_of_variation(y_true, y_pred, eps=1e-10)¶
Coefficient of Variation of the root mean squared error relative to the mean of the true values
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The Coefficient of Variation
- Return type:
float
- dysts.metrics.compute_metrics(y_true: ndarray, y_pred: ndarray, verbose: bool = False, include: list[str] | None = None, batch_axis: int | None = None) dict[str, float] ¶
Compute multiple time series metrics
- Parameters:
y_true (np.ndarray) – The true values of shape (…, T, …)
y_pred (np.ndarray) – The predicted values of shape (…, T, …)
verbose (bool) – Whether to print the computed metrics. Default is False.
include (optional, list) – The metrics to include. Default is None, which computes all metrics. Otherwise, specify a list of metrics to compute.
batch_axis (optional, int) – The axis to treat as the batch dimension. Default is None, which adds a singleton batchdimension at axis 0
- Returns:
A dictionary containing the computed metrics
- Return type:
dict
- Raises:
ValueError – If the batch dimension is not the same for y_true and y_pred
ValueError – If the shapes of y_true and y_pred are not broadcastable
Examples
>>> compute_metrics(y_true, y_pred) >>> compute_metrics(y_true, y_pred, batch_axis=1) >>> compute_metrics(y_true, y_pred, include=["mse", "mae"]) >>> compute_metrics(y_true, y_pred, include=["mse", "mae"], batch_axis=1)
- dysts.metrics.dtw(y_true, y_pred)¶
Compute the Dynamic Time Warping (DTW) distance between two time series.
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The DTW distance
- Return type:
float
- dysts.metrics.estimate_kl_divergence(true_orbit, generated_orbit, n_samples=1000, sigma_scale: float | None = 1.0) float ¶
Estimate KL divergence between observed and generated orbits using Gaussian Mixture Models (GMMs).
- Parameters:
observed_orbit (np.ndarray) – Observed orbit points, with shape (T, N) where T is the number of time steps and N is the dimensionality.
generated_orbit (np.ndarray) – Generated orbit points, with shape (T, N) where T is the number of time steps and N is the dimensionality.
n_samples (int) – Number of Monte Carlo samples.
sigma_scale (float) – Variance parameter for the GMMs. If None, the variance is estimated locally for each point.
- Returns:
Estimated KL divergence
- Return type:
float
References
Hess, Florian, et al. “Generalized teacher forcing for learning chaotic dynamics.” Proceedings of the 40th International Conference on Machine Learning. 2023.
- Development:
Rank-order (copula) transform each orbit coordinate, in order to reduce sensitivity to spacing among time series.
- dysts.metrics.find_sigma(dists, tol=1e-06)¶
Given a list of distances to k nearest neighbors, find the sigma for each point
- Parameters:
dists (np.ndarray) – A matrix of shape (k,)
tol (float) – The tolerance for the sigma
- Returns:
The sigma np.ndarray: The transformed distances
- Return type:
float
Examples
>>> sigma, dists_transformed = find_sigma(dists) >>> sigma, dists_transformed = find_sigma(dists, tol=1e-4)
- Raises:
ValueError – If the distance matrix is not a 2D array
- dysts.metrics.hellinger_distance(p, q, axis=0)¶
Compute the Hellinger distance between two distributions.
- Parameters:
p (np.ndarray) – The first distribution
q (np.ndarray) – The second distribution
axis (int) – The axis to sum over
- Returns:
The Hellinger distance
- Return type:
float
- dysts.metrics.horizoned_metric(y_true, y_pred, metric, *args, horizon=None, **kwargs)¶
Compute a metric over a range of horizons
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
metric (callable) – The metric function
*args – Additional arguments to pass to the metric function
horizon (int) – The maximum horizon to compute the metric over. If None, the horizon is set to the length of the time series
**kwargs – Additional keyword arguments to pass to the metric function
- Returns:
The metric values at each horizon
- Return type:
np.ndarray
- dysts.metrics.kendall(y_true, y_pred)¶
Kendall-Tau Correlation. Returns dimensionwise mean for multivariate time series of shape (T, D)
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The Kendall-Tau Correlation
- Return type:
float
- dysts.metrics.mae(y_true, y_pred)¶
Mean Absolute Error
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The MAE
- Return type:
float
- dysts.metrics.mape(y_true, y_pred, eps=1e-10)¶
The Mean Absolute Percentage Error
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The MAPE
- Return type:
float
- dysts.metrics.marre(y_true, y_pred, eps=1e-10)¶
Mean Absolute Ranged Relative Error
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The MARRE
- Return type:
float
- dysts.metrics.mase(y, yhat, y_train=None, m=1, time_dim=-1, eps=1e-10)¶
The mean absolute scaled error.
- Parameters:
y (ndarray) – The true values.
yhat (ndarray) – The predicted values.
y_train (ndarray) – The training values.
m (int) – The season length, which is the number of time steps that are skipped when computing the denominator. Default is 1.
time_dim (int) – The dimension of the time series. Default is -1.
- Returns:
The MASE error
- Return type:
mase_val (float)
- dysts.metrics.mse(y_true, y_pred)¶
Mean Squared Error
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The MSE
- Return type:
float
- dysts.metrics.msis(y, yhat_lower, yhat_upper, y_obs, m, time_dim=-1, a=0.05, eps=1e-10)¶
The mean scaled interval score.
- Parameters:
y (np.ndarray) – An array containing the true values.
yhat_lower – An array containing the a% quantile of the predicted distribution.
yhat_upper – An array containing the (1-a)% quantile of the predicted distribution.
y_obs – An array containing the training values.
m – The season length.
a – A scalar in [0, 1] specifying the quantile window to evaluate.
- Returns:
The scalar MSIS.
- dysts.metrics.mutual_information(y_true, y_pred)¶
Mutual Information. Returns dimensionwise mean for multivariate time series of shape (T, D). Computes the mutual information separately for each dimension and returns the mean.
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The Mutual Information
- Return type:
float
- dysts.metrics.nrmse(y_true, y_pred, eps=1e-10, scale=None)¶
Normalized Root Mean Squared Error
- Parameters:
y_true (np.ndarray) – True values of shape (T, D)
y_pred (np.ndarray) – Predicted values of shape (T, D)
eps (float) – Small value to avoid division by zero
scale (np.ndarray) – Standard deviation of the true values of shape (D,). If None, the standard deviation is computed from the true values.
- Returns:
NRMSE
- Return type:
float
- dysts.metrics.ope(y_true, y_pred)¶
Optimality Percentage Error
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The OPE
- Return type:
float
- dysts.metrics.pearson(y_true, y_pred)¶
Pearson Correlation. Returns dimensionwise mean for multivariate time series of shape (T, D)
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The Pearson Correlation
- Return type:
float
- dysts.metrics.r2_score(y_true, y_pred)¶
The R2 Score
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The R2 Score
- Return type:
float
- dysts.metrics.relu(x)¶
Rectified Linear Unit
- Parameters:
x (np.ndarray) – The input array
- Returns:
The output array
- Return type:
np.ndarray
- dysts.metrics.rmse(x, y)¶
Root Mean Squared Error
- Parameters:
x (np.ndarray) – The true values
y (np.ndarray) – The predicted values
- Returns:
The RMSE
- Return type:
float
- dysts.metrics.rmsle(y_true, y_pred, eps=1e-10)¶
Root Mean Squared Log Error. In case of negative values, the series is shifted to the positive domain.
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The RMSLE
- Return type:
float
- dysts.metrics.simplex_neighbors(X, metric='euclidean', k=20, tol=1e-06)¶
Compute the distance between points in a dataset using the simplex distance metric.
- Parameters:
X (np.ndarray) – dataset of shape (n, d)
Y (np.ndarray) – dataset of shape (m, d)
metric (str) – distance metric to use
k (int) – number of nearest neighbors to use in the distance calculation
tol (float) – tolerance for the distance calculation
- Returns:
weights matrix of shape (n,) idx (np.ndarray): index matrix of shape (n, k) sigmas (np.ndarray): sigmas matrix of shape (n,)
- Return type:
wgts (np.ndarray)
Examples
>>> wgts, idx, sigmas = simplex_neighbors(X) >>> wgts, idx, sigmas = simplex_neighbors(X, metric="cosine") >>> wgts, idx, sigmas = simplex_neighbors(X, k=10) >>> wgts, idx, sigmas = simplex_neighbors(X, tol=1e-4)
- dysts.metrics.smape(x, y, eps=1e-10, scaled=True)¶
Symmetric mean absolute percentage error
- dysts.metrics.spearman(y_true, y_pred)¶
Spearman Correlation. Returns dimensionwise mean for multivariate time series of shape (T, D)
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The Spearman Correlation
- Return type:
float
- dysts.metrics.wape(y_true, y_pred, eps=1e-10)¶
Weighted Absolute Percentage Error
- Parameters:
y_true (np.ndarray) – The true values
y_pred (np.ndarray) – The predicted values
- Returns:
The WAPE
- Return type:
float