Stimulus¶
This module provides convenient functions for synthesizing timeseries used as the input to the network.
hetero.stimulus is the dispatcher: it looks the label given on the
command line (--stim) up in the stim block of
hetero.config.CFG, calls the matching generator with that block’s
parameters, and concatenates the requested timeseries into the single input
u the network is driven with. The generators themselves are grouped into
three families, one module each:
hetero.stims.elementaryTrivial shapes – a null signal and a constant offset.
hetero.stims.mapsIterated one- and two-dimensional discrete maps.
hetero.stims.processesContinuous-time dynamical systems integrated onto a discrete time series.
Note
Because the map and process generators are the workhorses of the input benchmark, they follow the conventions of the ReservoirPy (https://github.com/reservoirpy/reservoirpy) package, with some adaptation for cross-modular compatibility.
- hetero.stimulus.synthesize(name, n_timesteps, dt_scaler, **stim_params)[source]¶
Synthesizes timeseries from the specified process.
- Parameters:
name (str) – The name of the underlying process. See notes for valid names.
n_timesteps (int) – Number of timesteps.
dt_scaler (float) – A scaling factor to up/down scale the integrator’s timestep (only relevant for processes.)
- Returns:
ndarray – Synthesized array
Notes
All supported generative processes can be categorized into three categories:
elementary functions: simple functions of time
maps: functions of previous step (without explicit notion of physical time)
processes: (system of) ODEs with explicit notion of time
The valid processes are listed below. Also see their respective documentation for potential arguments.
- Elementary functions
sin
sign
null
constant
- Maps
henon_map
logistic_map
narma
- Processes
lorenz
lorenz96
mackey_glass
multiscroll
doublescroll
rabinovich_fabrikant
rossler
kuramoto_sivashinsky
- hetero.stimulus.is_constant_stim(stim_params)[source]¶
Checks whether the stimulus configuration is a pure constant (DC) input.
A constant (DC) input carries no characteristic timescale. Hence, its temporal characterization (base-lag estimation) and the subsequent time rescaling are irrelevant and can be bypassed.
- Parameters:
stim_params (dict) – Stimulus parameters, e.g.
{'constant': {'amplitude': 1.}}or a combination thereof, e.g.{'constant': ..., 'constant-4': ...}.- Returns:
bool – True if every (compound) component is a
constantinput.- Return type:
bool
Elementary functions¶
- hetero.stims.elementary.null(n_timesteps, **kwargs)[source]¶
Generats a null (zero) stimulus.
- Parameters:
n_timesteps (int) – Number of timesteps to generate.
kwargs (dict)
- Returns:
np.ndarray of shape (n_timesteps, 1) – A zero 1-dimensional array.
- Return type:
ndarray
- hetero.stims.elementary.sin(n_timesteps, h=0.05, freq=1., phase=0.)[source]¶
Generates a sinusoidal input of given frequency.
- Parameters:
n_timesteps (int) – Number of timesteps to generate.
h (float, optional) – Time delta between two discrete timesteps, by default 0.05.
freq (float, optional) – Oscillation frequency, by default 1.
phase (float, optional) – Oscillation starting phase in radian, by default 0.
- Returns:
np.ndarray of shape (n_timesteps, 1) – A 1-dimensional array.
- Return type:
ndarray
- hetero.stims.elementary.sign(n_timesteps, h=0.05, freq=1., phase=0.)[source]¶
Generates a signal that is the sign of a sinusoidal input of given frequency.
- Parameters:
n_timesteps (int) – Number of timesteps to generate.
h (float, optional) – Time delta between two discrete timesteps, by default 0.05.
freq (float, optional) – Oscillation frequency, by default 1.
phase (float, optional) – Oscillation starting phase in radian, by default 0.
- Returns:
np.ndarray of shape (n_timesteps, 1) – A 1-dimensional array.
- Return type:
ndarray
- hetero.stims.elementary.sinabs(n_timesteps, h=0.05, freq=1., phase=0.)[source]¶
Generates the abs of a sinusoidal input of given frequency.
- Parameters:
n_timesteps (int) – Number of timesteps to generate.
h (float, optional) – Time delta between two discrete timesteps, by default 0.05.
freq (float, optional) – Oscillation frequency, by default 1.
phase (float, optional) – Oscillation starting phase in radian, by default 0.
- Returns:
np.ndarray of shape (n_timesteps, 1) – A 1-dimensional array.
- Return type:
ndarray
- hetero.stims.elementary.constant(n_timesteps, amplitude=1., h=0.05, **kwargs)[source]¶
Generates a constant amplitude input
- Parameters:
n_timesteps (int) – Number of timesteps to generate.
amplitude (float, optional) – Input amplitude.
h (float, optional) – Time delta between two discrete timesteps, by default 0.05. (unused: a constant input does not depend on time)
kwargs (dict)
- Returns:
np.ndarray of shape (n_timesteps, 1) – A 1-dimensional array.
- Return type:
ndarray
Maps¶
Note
This section is directly reproduced from the ReservoirPy (https://github.com/reservoirpy/reservoirpy) package, with some adaptation for cross-modular compatibility.
- hetero.stims.maps.henon_map(n_timesteps, a=1.4, b=0.3, x0=[0.0, 0.0], **kwargs)[source]¶
Hénon map discrete timeseries [2] [3].
\[\begin{split}x(n+1) &= 1 - ax(n)^2 + y(n)\\ y(n+1) &= bx(n)\end{split}\]- Parameters:
n_timesteps (int) – Number of timesteps to generate.
a (float, default to 1.4) – \(a\) parameter of the system.
b (float, default to 0.3) – \(b\) parameter of the system.
x0 (array-like of shape (2,), default to [0.0, 0.0]) – Initial conditions of the system.
- Returns:
array of shape (n_timesteps, 2) – Hénon map discrete timeseries.
- Return type:
ndarray
- hetero.stims.maps.logistic_map(n_timesteps, r=3.9, x0=0.5, **kwargs)[source]¶
Logistic map discrete timeseries [4] [5].
\[x(n+1) = rx(n)(1-x(n))\]- Parameters:
n_timesteps (int) – Number of timesteps to generate.
r (float, default to 3.9) – \(r\) parameter of the system.
x0 (float, default to 0.5) – Initial condition of the system.
- Returns:
array of shape (n_timesteps, 1) – Logistic map discrete timeseries.
- Return type:
ndarray
- hetero.stims.maps.narma(n_timesteps, order=30, a1=0.2, a2=0.04, b=1.5, c=0.001, x0=[0.0], seed=None, h=1.0)[source]¶
Non-linear Autoregressive Moving Average (NARMA) timeseries, as first defined in [14], and as used in [15].
NARMA n-th order dynamical system is defined by the recurrent relation:
\[y[t+1] = a_1 y[t] + a_2 y[t] (\sum_{i=0}^{n-1} y[t-i]) + b u[t-( n-1)]u[t] + c\]where \(u[t]\) are sampled following a uniform distribution in \([0, 0.5]\).
- Parameters:
n_timesteps (int) – Number of timesteps to generate.
order (int, default to 30) – Order of the system.
a1 (float, default to 0.2) – \(a_1\) parameter of the system.
a2 (float, default to 0.04) – \(a_2\) parameter of the system.
b (float, default to 1.5) – \(b\) parameter of the system.
c (float, default to 0.001) – \(c\) parameter of the system.
x0 (array-like of shape (init_steps,), default to [0.0]) – Initial conditions of the system.
seed (int or
numpy.random.Generator, optional) – Random state seed for reproducibility.h (float)
- Returns:
array of shape (n_timesteps, 1) – NARMA timeseries.
- Return type:
ndarray
Processes¶
Note
This section is directly reproduced from the ReservoirPy (https://github.com/reservoirpy/reservoirpy) package, with some adaptation for cross-modular compatibility.
- hetero.stims.processes.lorenz(n_timesteps, rho=28.0, sigma=10.0, beta=8.0 / 3.0, x0=[-15.0577155, -19.28572772, 31.35055511], h=0.03, **kwargs)[source]¶
Lorenz attractor timeseries as defined by Lorenz in 1963 [6] [7].
\[\begin{split}\frac{\mathrm{d}x}{\mathrm{d}t} &= \sigma (y-x) \\ \frac{\mathrm{d}y}{\mathrm{d}t} &= x(\rho - z) - y \\ \frac{\mathrm{d}z}{\mathrm{d}t} &= xy - \beta z\end{split}\]- Parameters:
n_timesteps (int) – Number of timesteps to generate.
rho (float, default to 28.0) – \(\rho\) parameter of the system.
sigma (float, default to 10.0) – \(\sigma\) parameter of the system.
beta (float, default to 8/3) – \(\beta\) parameter of the system.
x0 (array-like of shape (3,), default to [1.0, 1.0, 1.0]) – Initial conditions of the system.
h (float, default to 0.03) – Time delta between two discrete timesteps.
**kwargs – Other parameters to pass to the scipy.integrate.solve_ivp solver.
- Returns:
array of shape (n_timesteps, 3) – Lorenz attractor timeseries.
- Return type:
ndarray
- hetero.stims.processes.mackey_glass(n_timesteps, tau=17, a=0.2, b=0.1, n=10, x0=1.2, h=1.0, seed=None, **kwargs)[source]¶
Mackey-Glass timeseries [8] [9], computed from the Mackey-Glass delayed differential equation.
\[\frac{x}{t} = \frac{ax(t-\tau)}{1+x(t-\tau)^n} - bx(t)\]- Parameters:
n_timesteps (int) – Number of timesteps to compute.
tau (int, default to 17) – Time delay \(\tau\) of Mackey-Glass equation. By defaults, equals to 17. Other values can change the choatic behaviour of the timeseries.
a (float, default to 0.2) – \(a\) parameter of the equation.
b (float, default to 0.1) – \(b\) parameter of the equation.
n (int, default to 10) – \(n\) parameter of the equation.
x0 (float, optional, default to 1.2) – Initial condition of the timeseries.
h (float, default to 1.0) – Time delta between two discrete timesteps.
seed (int or
numpy.random.Generator, optional) – Random state seed for reproducibility.
- Returns:
array of shape (n_timesteps, 1) – Mackey-Glass timeseries.
- Return type:
ndarray
Note
As Mackey-Glass is defined by delayed time differential equations, the first timesteps of the timeseries can’t be initialized at 0 (otherwise, the first steps of computation involving these not-computed-yet-timesteps would yield inconsistent results). A random number generator is therefore used to produce random initial timesteps based on the value of the initial condition passed as parameter. A default seed is hard-coded to ensure reproducibility in any case. It can be changed with the
set_seed()function.
- hetero.stims.processes.multiscroll(n_timesteps, a=40.0, b=3.0, c=28.0, x0=[-0.1, 0.5, -0.6], h=0.01, **kwargs)[source]¶
Double scroll attractor timeseries [10] [11], a particular case of multiscroll attractor timeseries.
\[\begin{split}\frac{\mathrm{d}x}{\mathrm{d}t} &= a(y - x) \\ \frac{\mathrm{d}y}{\mathrm{d}t} &= (c - a)x - xz + cy \\ \frac{\mathrm{d}z}{\mathrm{d}t} &= xy - bz\end{split}\]- Parameters:
n_timesteps (int) – Number of timesteps to generate.
a (float, default to 40.0) – \(a\) parameter of the system.
b (float, default to 3.0) – \(b\) parameter of the system.
c (float, default to 28.0) – \(c\) parameter of the system.
x0 (array-like of shape (3,), default to [-0.1, 0.5, -0.6]) – Initial conditions of the system.
h (float, default to 0.01) – Time delta between two discrete timesteps.
- Returns:
array of shape (n_timesteps, 3) – Multiscroll attractor timeseries.
- Return type:
ndarray
- hetero.stims.processes.doublescroll(n_timesteps, r1=1.2, r2=3.44, r4=0.193, ir=2 * 2.25e-5, beta=11.6, x0=[0.37926545, 0.058339, -0.08167691], h=0.25, **kwargs)[source]¶
Double scroll attractor timeseries [10] [11], a particular case of multiscroll attractor timeseries.
\[\begin{split}\frac{\mathrm{d}V_1}{\mathrm{d}t} &= \frac{V_1}{R_1} - \frac{\Delta V}{R_2} - 2I_r \sinh(\beta\Delta V) \\ \frac{\mathrm{d}V_2}{\mathrm{d}t} &= \frac{\Delta V}{R_2} +2I_r \sinh(\beta\Delta V) - I\\ \frac{\mathrm{d}I}{\mathrm{d}t} &= V_2 - R_4 I\end{split}\]where \(\Delta V = V_1 - V_2\).
- Parameters:
n_timesteps (int) – Number of timesteps to generate.
r1 (float, default to 1.2) – \(R_1\) parameter of the system.
r2 (float, default to 3.44) – \(R_2\) parameter of the system.
r4 (float, default to 0.193) – \(R_4\) parameter of the system.
ir (float, default to 2*2e.25e-5) – \(I_r\) parameter of the system.
beta (float, default to 11.6) – \(\beta\) parameter of the system.
x0 (array-like of shape (3,), default to [0.37926545, 0.058339, -0.08167691]) – Initial conditions of the system.
h (float, default to 0.01) – Time delta between two discrete timesteps.
- Returns:
array of shape (n_timesteps, 3) – Multiscroll attractor timeseries.
- Return type:
ndarray
- hetero.stims.processes.rabinovich_fabrikant(n_timesteps, alpha=1.1, gamma=0.89, x0=[-1, 0, 0.5], h=0.05, **kwargs)[source]¶
Rabinovitch-Fabrikant system [12] [13] timeseries.
\[\begin{split}\frac{\mathrm{d}x}{\mathrm{d}t} &= y(z - 1 + x^2) + \gamma x \\ \frac{\mathrm{d}y}{\mathrm{d}t} &= x(3z + 1 - x^2) + \gamma y \\ \frac{\mathrm{d}z}{\mathrm{d}t} &= -2z(\alpha + xy)\end{split}\]- Parameters:
n_timesteps (int) – Number of timesteps to generate.
alpha (float, default to 1.1) – \(\alpha\) parameter of the system.
gamma (float, default to 0.89) – \(\gamma\) parameter of the system.
x0 (array-like of shape (3,), default to [-1, 0, 0.5]) – Initial conditions of the system.
h (float, default to 0.05) – Time delta between two discrete timesteps.
**kwargs – Other parameters to pass to the scipy.integrate.solve_ivp solver.
- Returns:
array of shape (n_timesteps, 3) – Rabinovitch-Fabrikant system timeseries.
- Return type:
ndarray
- hetero.stims.processes.lorenz96(n_timesteps, warmup=0, N=36, F=8.0, dF=0.01, h=0.01, x0=None, **kwargs)[source]¶
Lorenz96 attractor timeseries as defined by Lorenz in 1996 [17].
\[\frac{\mathrm{d}x_i}{\mathrm{d} t} = (x_{i+1} - x_{i-2}) x_{i-1} - x_i + F\]where \(i = 1, \dots, N\) and \(x_{-1} = x_{N-1}\) and \(x_{N+1} = x_1\) and \(N \geq 4\).
- Parameters:
n_timesteps (int) – Number of timesteps to generate.
warmup (int, default to 0) – Number of timesteps to discard at the begining of the signal, to remove transient states.
N (int, default to 36) – Dimension of the system.
F (float, default to F) – \(F\) parameter of the system.
dF (float, default to 0.01) – Pertubation applied to initial condition if x0 is None.
h (float, default to 0.01) – Time delta between two discrete timesteps.
x0 (array-like of shape (N,), default to None) – Initial conditions of the system. If None, the array is initialized to an array of shape (N, ) with value F, except for the first value of the array that takes the value F + dF.
**kwargs – Other parameters to pass to the scipy.integrate.solve_ivp solver.
- Returns:
array of shape (n_timesteps - warmup, N) – Lorenz96 timeseries.
- Return type:
ndarray
- hetero.stims.processes.rossler(n_timesteps, a=0.2, b=0.2, c=5.7, x0=[-0.1, 0.0, 0.02], h=0.1, **kwargs)[source]¶
Rössler attractor timeseries [18].
\[\begin{split}\frac{\mathrm{d}x}{\mathrm{d}t} &= -y - z \\ \frac{\mathrm{d}y}{\mathrm{d}t} &= x + a y \\ \frac{\mathrm{d}z}{\mathrm{d}t} &= b + z (x - c)\end{split}\]- Parameters:
n_timesteps (int) – Number of timesteps to generate.
a (float, default to 0.2) – \(a\) parameter of the system.
b (float, default to 0.2) – \(b\) parameter of the system.
c (float, default to 5.7) – \(c\) parameter of the system.
x0 (array-like of shape (3,), default to [-0.1, 0.0, 0.02]) – Initial conditions of the system.
h (float, default to 0.1) – Time delta between two discrete timesteps.
**kwargs – Other parameters to pass to the scipy.integrate.solve_ivp solver.
- Returns:
array of shape (n_timesteps, 3) – Rössler attractor timeseries.
- Return type:
ndarray
- hetero.stims.processes.kuramoto_sivashinsky(n_timesteps, warmup=0, N=128, M=16, x0=None, h=0.25)[source]¶
Kuramoto-Sivashinsky oscillators [19] [20] [21].
\[y_t = -yy_x - y_{xx} - y_{xxxx}, ~~ x \in [0, 32\pi]\]This 1D partial differential equation is solved using ETDRK4 (Exponential Time-Differencing 4th order Runge-Kutta) method, as described in [22].
- Parameters:
n_timesteps (int) – Number of timesteps to generate.
warmup (int, default to 0) – Number of timesteps to discard at the begining of the signal, to remove transient states.
N (int, default to 128) – Dimension of the system.
M (float, default to 0.2) – Number of points for complex means. Modify beahviour of the resulting multivariate timeseries.
x0 (array-like of shape (N,), default to None.) – Initial conditions of the system. If None, x0 is equal to \(\cos (\frac{y}{M}) * (1 + \sin(\frac{y}{M}))\) with \(y = 2M\pi x / N, ~~ x \in [1, N]\).
h (float, default to 0.25) – Time delta between two discrete timesteps.
- Returns:
array of shape (n_timesteps - warmup, N) – Kuramoto-Sivashinsky equation solution.
- Return type:
ndarray