eventseries.event_series¶
Provides class for event series analysis, namely event synchronization (ES) and event coincidence analysis (ECA). In addition, a method for the generation of binary event series from continuous time series data is included. When instantiating a class, data must either be passed as an event matrix (for details see below) or as a continuous time series. Using the class, an ES or ECA matrix can be calculated to generate a climate network using the EventSeriesClimateNetwork class. Both ES and ECA may be called without instantiating an object of the class. Significance levels are provided using analytic calculations using Poisson point processes as a null model (for ECA only) or a Monte Carlo approach.
Modifications vs. original pyunicorn EventSeries¶
- Modification 1 (constructor):
Removed the axis-swap heuristic that transposed data when the number of variables exceeded the number of timesteps. The heuristic assumed that datasets with more variables than timesteps were transposed by mistake, which is not always true.
- Modification 2 (make_event_matrix):
Replaced np.quantile with np.nanquantile so that time series containing NaN values are handled gracefully instead of raising an error.
- Modification 3 (matrix loops):
Added tqdm progress bars to _ndim_event_synchronization and _ndim_event_coincidence_analysis for visual feedback during long runs.
- Modification 4 (getters):
Added get_T(), get_N(), get_timestamps(), get_taumax(), get_lag() accessor methods to expose key instance attributes without name-mangling gymnastics.
- Optimization 1 — Sparse binary-search ES with lag support (finite taumax):
For finite taumax, precomputes sorted inner-event arrays once per node and uses np.searchsorted to find only the event pairs within the lag-shifted taumax window. Complexity O(N²·L·taumax/T) vs O(N²·L²). Results are exact (atol < 1e-12 vs pairwise reference).
- Optimization 2 — Blocked dense ES (infinite taumax, lag=0):
Falls back to a 4-D blocked-dense tensor kernel that vectorises the double-count correction loop — the main bottleneck in the original code. Block size is tunable; joblib parallelization is supported.
- Optimization 3 — Vectorized ECA via cumsum + BLAS (integer timestamps):
For uniform integer timestamps and integer-valued lag, builds lag=0 smeared indicator matrices with cumsum rolling windows, shifts by lag steps, then uses a single BLAS matrix multiply. Complexity O(T·N + N²). Precision is identical to pairwise within float32 rounding (atol < 1e-6).
- Optimization 4 — Optional joblib parallelization:
All kernel dispatchers accept an n_jobs keyword argument. If joblib is installed, computation is distributed across n_jobs worker processes. Falls back to a single-process loop when joblib is absent.
Contributors¶
Guruprem Bishnoi — Modifications 1–4 and Optimizations 1–4 (2026)
- class pyunicorn.eventseries.event_series.EventSeries(data, *, timestamps=None, taumax=inf, lag=0.0, threshold_method=None, threshold_values=None, threshold_types=None)[source]¶
Bases:
Cached- __cache_state__() Tuple[Hashable, ...][source]¶
Hashable tuple of mutable object attributes, which will determine the instance identity for ALL cached method lookups in this class, in addition to the built-in object id(). Returning an empty tuple amounts to declaring the object immutable in general. Mutable dependencies that are specific to a method should instead be declared via @Cached.method(attrs=(…)).
NOTE:
A subclass is responsible for the consistency and cost of this state descriptor. For example, hashing a large array attribute may be circumvented by declaring it as a property, with a custom setter method that increments a dedicated mutation counter.
- __init__(data, *, timestamps=None, taumax=inf, lag=0.0, threshold_method=None, threshold_values=None, threshold_types=None)[source]¶
Initialize an instance of EventSeries. Input data must be a 2D numpy array with time as the first axis and variables as the second axis. Event data is stored as an eventmatrix.
Format of eventmatrix: An eventmatrix is a 2D numpy array with the first dimension covering the timesteps and the second dimensions covering the variables. Each variable at a specific timestep is either ‘1’ if an event occured or ‘0’ if it did not, e.g. for 3 variables with 10 timesteps the eventmatrix could look like
- array([[0, 1, 0],
[1, 0, 1], [0, 0, 0], [1, 0, 1], [0, 1, 0], [0, 0, 0], [1, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 0]])
If input data is not provided as an eventmatrix, the constructor tries to generate one using the make_event_matrix method. Default keyword arguments are used in this case.
- Parameters:
data (2D Numpy array [time, variables]) – Event series array or array of non-binary variable values
timestamps (1D Numpy array) – Time points of events of data. If not provided, integer values are used
taumax (float) – maximum time difference between two events to be considered synchronous. Caution: For ES, the default is np.inf because of the intrinsic dynamic coincidence interval in ES. For ECA, taumax is a parameter of the method that needs to be defined!
lag (float) – extra time lag between the event series
threshold_method (str 'quantile' or 'value' or 1D numpy array or str 'quantile' or 'value') – specifies the method for generating a binary event matrix from an array of continuous time series. Default: None
threshold_values (1D Numpy array or float) – quantile or real number determining threshold for each variable. Default: None.
threshold_types (str 'above' or 'below' or 1D list of strings 'above' or 'below') – Determines for each variable if event is below or above threshold
- _compute_eca_pairwise(window_type)[source]¶
Pairwise ECA loop — identical to original pyunicorn. Modification 3: tqdm progress bar added.
- _compute_eca_vectorized_lag(window_type)[source]¶
Optimization 3: Vectorized ECA via cumsum rolling windows + BLAS matrix multiply, extended to support any integer-valued lag.
Core idea: build the lag=0 smeared indicator matrix with a cumsum rolling window, then shift it by lag steps along the time axis. Boundary corrections mirror the pairwise formula exactly.
For lag=0 the output is bit-for-bit identical to the pairwise path within float32 rounding (atol < 1e-6 vs pairwise reference). Complexity: O(T·N + N²) vs O(N²·L²) for the pairwise approach.
- _compute_es_matrix_blocked(node_data, block_size=32, n_jobs=1)[source]¶
Optimization 2: Assemble the full N×N directed ES matrix from blocked 4-D computations (infinite taumax, lag=0).
Optimization 4: n_jobs > 1 uses joblib if available.
- _compute_es_matrix_sparse_lag(node_data, n_jobs=1)[source]¶
Optimization 1: Assemble the full N×N directed ES matrix using the lag-aware sparse binary-search kernel. Works for any scalar lag value.
Row-based chunking minimises joblib serialisation overhead. Optimization 4: n_jobs > 1 uses joblib if available.
- _eca_coincidence_rate(eventseriesx, eventseriesy, *, window_type='symmetric', ts1=None, ts2=None)[source]¶
Event coincidence analysis: Returns the coincidence rates of two event series for both directions
- Parameters:
eventseriesx (1D Numpy array) – Event series containing ‘0’s and ‘1’s
eventseriesy (1D Numpy array) – Event series containing ‘0’s and ‘1’s
ts1 (1D Numpy array) – Event time array containing time points when events of event series 1 occur, not obligatory
ts2 (1D Numpy array) – Event time array containing time points when events of event series 2 occur, not obligatory
window_type (str {'retarded', 'advanced', 'symmetric'}) – Only for ECA. Determines if precursor coincidence rate (‘advanced’), trigger coincidence rate (‘retarded’) or a general coincidence rate with the symmetric interval [-taumax, taumax] are computed (‘symmetric’). Default: ‘symmetric’
- Return type:
list
- Returns:
Precursor coincidence rates [XY, YX]
- _empirical_percentiles(method=None, n_surr=1000, symmetrization='directed', window_type='symmetric')[source]¶
Compute p-values of event synchronisation (ES) and event coincidence analysis (ECA) using a Monte-Carlo approach. Surrogates are obtained by shuffling the event series. ES/ECA scores of the surrogate event series are computed and p-values are the empirical percentiles of the original event series compared to the ES/ECA scores of the surrogates.
- Parameters:
method (str 'ES' or 'ECA') – determines if ES or ECA should be used
n_surr (int) – number of surrogates for Monte-Carlo method
symmetrization (str {'directed', 'symmetric', 'antisym', 'mean', 'max', 'min'} for ES, str {'directed', 'mean', 'max', 'min'} for ECA) – determines if and which symmetrisation method should be used for the ES/ECA score matrix
window_type (str {'retarded', 'advanced', 'symmetric'}) – Only for ECA. Determines if precursor coincidence rate (‘advanced’), trigger coincidence rate (‘retarded’) or a general coincidence rate with the symmetric interval [-taumax, taumax] are computed (‘symmetric’). Default: ‘symmetric’
- Return type:
2D numpy array
- Returns:
p-values of the ES/ECA scores for all
- _ndim_event_coincidence_analysis(window_type='symmetric')[source]¶
Computes NxN event coincidence matrix of event coincidence rate.
- Routing (Optimization 3):
uniform integer timestamps + integer lag → vectorized cumsum + BLAS otherwise → pairwise loop (original)
- Parameters:
window_type (str {'retarded', 'advanced', 'symmetric'}) – Only for ECA. Determines if precursor coincidence rate (‘advanced’), trigger coincidence rate (‘retarded’) or a general coincidence rate with the symmetric interval [-taumax, taumax] are computed (‘symmetric’). Default: ‘symmetric’
- Return type:
NxN numpy array where N is the number of variables of the eventmatrix
- Returns:
event coincidence matrix
- _ndim_event_synchronization()[source]¶
Compute NxN event synchronization matrix [i,j] with event synchronization from j to i without symmetrization.
- Routing (Optimizations 1 & 2):
finite taumax, any lag → sparse binary-search (fast, exact) infinite taumax, lag=0 → blocked-dense 4-D (vectorized) infinite taumax, lag≠0 → pairwise loop (fallback)
- Return type:
NxN numpy array where N is the number of variables of the eventmatrix
- Returns:
event synchronization matrix
- _ndim_event_synchronization_pairwise()[source]¶
Pairwise ES loop — identical to original pyunicorn. Used as fallback when taumax=inf and lag≠0.
Modification 3: tqdm progress bar added.
- _precompute_es_node_data()[source]¶
Optimization 1 / 2: Precompute inner-event times and per-event dynamic tau2 for every node. Called once before the matrix loop.
- static _symmetrization_antisym(matrix)[source]¶
Helper function for symmetrization options
- Parameters:
matrix (2D numpy array) – pairwise ECA/ES scores of data
- Return type:
2D numpy array
- Returns:
antisymmetrized matrix
- static _symmetrization_directed(matrix)[source]¶
Helper function for symmetrization options
- Parameters:
matrix (2D numpy array) – pairwise ECA/ES scores of data
- Return type:
2D numpy array
- Returns:
original matrix
- static _symmetrization_max(matrix)[source]¶
Helper function for symmetrization options
- Parameters:
matrix (2D numpy array) – pairwise ECA/ES scores of data
- Return type:
2D numpy array
- Returns:
symmetrized matrix using element-wise maximum of matrix and transposed matrix
- static _symmetrization_mean(matrix)[source]¶
Helper function for symmetrization options
- Parameters:
matrix (2D numpy array) – pairwise ECA/ES scores of data
- Return type:
2D numpy array
- Returns:
symmetrized matrix using element-wise mean of matrix and transposed matrix
- static _symmetrization_min(matrix)[source]¶
Helper function for symmetrization options
- Parameters:
matrix (2D numpy array) – pairwise ECA/ES scores of data
- Return type:
2D numpy array
- Returns:
symmetrized matrix using element-wise minimum of matrix and transposed matrix
- static _symmetrization_symmetric(matrix)[source]¶
Helper function for symmetrization options
- Parameters:
matrix (2D numpy array) – pairwise ECA/ES scores of data
- Return type:
2D numpy array
- Returns:
symmetrized matrix
- event_analysis_significance(*, method=None, surrogate='shuffle', n_surr=1000, symmetrization='directed', window_type='symmetric')[source]¶
Returns significance levels (1 - p-values) for event synchronisation (ES) and event coincidence analysis (ECA). For ECA, there is an analytic option providing significance levels based on independent Poisson processes. The ‘shuffle’ option uses a Monte-Carlo approach, calculating ES or ECA scores for surrogate event time series obtained by shuffling the original event time series. The significance levels are the empirical percentiles of the ES/ECA scores of the original event series compared with the scores of the surrogate data.
- Parameters:
method (str 'ES' or 'ECA') – determines if ES or ECA should be used
surrogate (str 'analytic' or 'shuffle') – determines if p-values should be calculated using a Monte-Carlo method or (only for ECA) an analytic Poisson process null model
n_surr (int) – number of surrogates for Monte-Carlo method
symmetrization (str {'directed', 'symmetric', 'antisym', 'mean', 'max', 'min'} for ES, str {'directed', 'mean', 'max', 'min'} for ECA) – determines if and which symmetrisation method should be used for the ES/ECA score matrix
window_type (str {'retarded', 'advanced', 'symmetric'}) – Only for ECA. Determines if precursor coincidence rate (‘advanced’), trigger coincidence rate (‘retarded’) or a general coincidence rate with the symmetric interval [-taumax, taumax] are computed (‘symmetric’). Default: ‘symmetric’
- Return type:
2D numpy array
- Returns:
significance levels of the ES/ECA scores for all pairs of event series in event matrix
- static event_coincidence_analysis(eventseriesx, eventseriesy, taumax, *, ts1=None, ts2=None, lag=0.0)[source]¶
Event coincidence analysis: Returns the precursor and trigger coincidence rates of two event series X and Y following the algorithm described in [Odenweller2020].
- Parameters:
eventseriesx (1D Numpy array) – Event series containing ‘0’s and ‘1’s
eventseriesy (1D Numpy array) – Event series containing ‘0’s and ‘1’s
ts1 (1D Numpy array) – Event time array containing time points when events of event series 1 occur, not obligatory
ts2 (1D Numpy array) – Event time array containing time points when events of event series 2 occur, not obligatory
taumax (float) – coincidence interval width
lag (int) – lag parameter
- Return type:
list
- Returns:
[Precursor coincidence rate XY, Trigger coincidence rate XY, Precursor coincidence rate YX, Trigger coincidence rate YX]
- event_series_analysis(method='ES', symmetrization='directed', window_type='symmetric')[source]¶
Returns the NxN matrix of the chosen event series measure where N is the number of variables. The entry [i, j] denotes the event synchronization or event coincidence analysis from variable j to variable i. According to the ‘symmetrization’ parameter the event series measure matrix is symmetrized or not.
The event coincidence rate of ECA is calculated according to the formula: r(Y|X, DeltaT1, DeltaT2, tau) = 1/N_X sum_{i=1}^{N_X} Theta[sum{j=1}^{N_Y} 1_[DeltaT1, DeltaT2] (t_i^X - (t_j^Y + tau))], where X is the first input event series, Y the second input event series, N_X the number of events in X, DeltaT1 and DeltaT2 the given coincidence interval boundaries, tau the lag between X and Y, Theta the Heaviside function and 1 the indicator function.
- Parameters:
method (str 'ES' or 'ECA') – determines if ES or ECA should be used
symmetrization (str {'directed', 'symmetric', 'antisym', 'mean', 'max', 'min'} for ES, str {'directed', 'mean', 'max', 'min'} for ECA) – determines if and which symmetrisation method should be used for the ES/ECA score matrix
window_type (str {'retarded', 'advanced', 'symmetric'}) – Only for ECA. Determines if precursor coincidence rate (‘advanced’), trigger coincidence rate (‘retarded’) or a general coincidence rate with the symmetric interval [-taumax, taumax] are computed (‘symmetric’). Default: ‘symmetric’
- Return type:
2D numpy array
- Returns:
pairwise event synchronization or pairwise coincidence rates symmetrized according to input parameter ‘symmetrization’
- static event_synchronization(eventseriesx, eventseriesy, *, ts1=None, ts2=None, taumax=inf, lag=0.0)[source]¶
Calculates the directed event synchronization from two event series X and Y using the algorithm described in [Quiroga2002], [Odenweller2020]
- Parameters:
eventseriesx (1D Numpy array) – Event series containing ‘0’s and ‘1’s
eventseriesy (1D Numpy array) – Event series containing ‘0’s and ‘1’s
ts1 (1D Numpy array) – Event time array containing time points when events of event series 1 occur, not obligatory
ts2 (1D Numpy array) – Event time array containing time points when events of event series 2 occur, not obligatory
taumax (float) – maximum distance of two events to be counted as synchronous
lag (float) – delay between the two event series, the second event series is shifted by the value of lag
- Return type:
list
- Returns:
[Event synchronization XY, Event synchronization YX]
- static make_event_matrix(data, threshold_method='quantile', threshold_values=None, threshold_types=None)[source]¶
Create a binary event matrix from continuous time series data. Data format is eventmatrix, i.e. a 2D numpy array with first dimension covering time and second dimension covering the values of the variables.
- Parameters:
data (2D numpy array) – Continuous input data
threshold_method (str 'quantile' or 'value' or 1D numpy array of strings 'quantile' or 'value') – specifies the method for generating a binary event matrix from an array of continuous time series. Default: ‘quantile’
threshold_values (1D Numpy array or float) – quantile or real number determining threshold for each variable. Default: None.
threshold_types (str 'above' or 'below' or 1D list of strings 'above' or 'below') – Determines for each variable if event is below or above threshold
- Return type:
2D numpy array
- Returns:
eventmatrix
- pyunicorn.eventseries.event_series._compute_es_block(node_data, block_a, block_b)[source]¶
Exact ES for all node pairs in two blocks via 4-D dense boolean tensors.
Vectorises the double-count correction loop that is the bottleneck in pyunicorn’s pairwise code. Used by the blocked-dense kernel (Opt 2).
- pyunicorn.eventseries.event_series._compute_es_pair_sparse_lag(tx, tau2x, ty, tau2y, *, taumax, lag)[source]¶
Exact ES for one pair using sorted inner-event times + binary search, extended to support any scalar lag (Optimization 1).
Parameters¶
tx, tau2x : 1-D float64 — inner event times and per-event tau2 for X ty, tau2y : 1-D float64 — inner event times and per-event tau2 for Y taumax : float — coincidence window cap (must be finite) lag : float — time lag (Y is conceptually shifted by +lag)
Returns¶
(countxy / norm, countyx / norm) : float64 pair