SIBERIA: SIgned BEnchmarks foR tIme series Analysis
SIBERIA is a Python 3 package for rigorous signed time-series network analysis.
Starting from an \(N \times T\) matrix of standardized time series, it builds signed co-fluctuation signatures, fits maximum-entropy null models, and produces validated signed graphs that can be analyzed via community detection and block-structure inspection.
SIBERIA implements advanced null models (bSRGM, bSCM, plus a simple naive projection) to distinguish meaningful mesoscale structure from noise, supporting reproducible and interpretable time-series network analysis.
Main Features
SIBERIA includes methods to:
Compute binary signature matrices for co-fluctuations.
Fit maximum-entropy null models (
bSRGM,bSCM) with LSQ or fixed-point solvers.Predict event probabilities (
pit_plus,pit_minus) from fitted parameters.Compare empirical signatures with null-model signatures via ensemble and analytical distributions and KS scores.
Build signed graphs via analytical p-values and optional FDR correction.
Perform community detection minimizing either - the BIC of a signed SBM (
method="bic"), or - the signed network frustration (method="frustration").Visualize results as adjacency heatmaps, community-reordered matrices, and community-level block matrices.
For more information about maximum-entropy methods, visit Maximum Entropy Hub.
Citation
If you use SIBERIA in your research, please cite the following paper:
@misc{divece2025assessingimbalancesignedbrain,
title={Assessing (im)balance in signed brain networks},
author={Marzio Di Vece and Emanuele Agrimi and Samuele Tatullo and Tommaso Gili and Miguel Ibáñez-Berganza and Tiziano Squartini},
year={2025},
eprint={2508.00542},
archivePrefix={arXiv},
primaryClass={physics.soc-ph},
url={https://arxiv.org/abs/2508.00542},
}
Installation
SIBERIA can be installed via pip:
pip install siberia
If you already installed the package and want to upgrade it:
pip install siberia --upgrade
Dependencies
SIBERIA uses the following dependencies:
numpy for numerical operations
scipy for optimization and statistical functions
pandas for structured data handling
fast-poibin for Poisson–Binomial distributions
joblib for parallel computation
statsmodels for multiple testing corrections (FDR)
matplotlib and seaborn for visualization
tqdm for progress bars
numba for accelerating heavy computations
They can be easily installed via pip:
pip install numpy scipy pandas fast-poibin joblib statsmodels matplotlib seaborn tqdm numba
How-to Guidelines
The main entry point of SIBERIA is the TSeries class, initialized with an
\(N \times T\) float matrix representing \(N\) time series of length \(T\).
If the rows are not standardized (mean ≈ 0, std ≈ 1), they are standardized internally.
Initialization
from siberia import TSeries
import numpy as np
# Tij is a 2D numpy array of shape (N, T) with float values
Tij = np.asarray(Tij, dtype=float)
T = TSeries(data=Tij, n_jobs=4)
After initialization you can explore marginal statistics of the binarized series:
T.ai_plus, T.ai_minus # row-wise positive / negative counts
T.kt_plus, T.kt_minus # column-wise positive / negative counts
T.a_plus, T.a_minus # total positive / negative counts
Computing the Signature
The signature captures concordant and discordant co-fluctuation motifs:
binary_signature = T.compute_signature()
Internally:
Concordant motifs = positive–positive + negative–negative
Discordant motifs = positive–negative + negative–positive
Binary signature = concordant − discordant
The result is stored in:
T.binary_signature
Fitting Null Models
You can list the available models:
T.implemented_models
# ['naive', 'bSRGM', 'bSCM']
Choose and fit a maximum-entropy model:
T.fit(
model="bSCM", # 'naive', 'bSRGM', or 'bSCM'
maxiter=1000,
max_nfev=1000,
tol=1e-8,
eps=1e-8,
solver_type="fixed_point" # 'fixed_point' or 'lsq' for bSCM
)
After fitting, the following attributes become available:
T.params # fitted parameters
T.ll # log-likelihood
T.jac # Jacobian of the constraints
T.norm # infinite norm of the Jacobian
T.norm_rel_error # relative norm of the constraint error
T.aic # Akaike Information Criterion
Predicting Event Probabilities
Compute the expected probability of observing positive and negative events in each \((i, t)\) entry:
pit_plus, pit_minus = T.predict()
These matrices are stored in:
T.pit_plus
T.pit_minus
and represent the null-model probabilities for positive and negative events for each time series and time step.
Checking Signature Distributions
You can compare the empirical signature with the null-model signature distributions using ensemble sampling and analytical calculations, summarized by a Kolmogorov–Smirnov score:
ks_score = T.check_distribution_signature(
n_ensemble=1000,
ks_score=True,
alpha=0.05
)
This method:
Generates an ensemble of signatures from the fitted model.
Computes analytical signature distributions (binomial / Poisson–Binomial).
Performs KS tests for node pairs and returns a normalized KS score in \([0, 1]\).
The outputs are stored as:
T.ks_score # fraction of pairs where p_KS >= alpha
T.ensemble_signature # N × N × n_ensemble
T.analytical_signature # N × N × n_ensemble
T.analytical_signature_dist # N × N × (T+1) PMFs (bSCM) or equivalent
A higher ks_score indicates better agreement between ensemble and analytical signatures.
Building Signed Graphs
From the empirical signature and the fitted model, you can construct a signed adjacency matrix using analytical p-values and optional FDR correction:
graph = T.build_graph(
fdr_correction_flag=True,
alpha=0.05
)
For
model='naive', the graph is simply the sign of the empirical binary signature.For
model='bSRGM'andmodel='bSCM', SIBERIA: - Computes analytical p-values for concordant motifs under the fitted model. - Optionally applies Benjamini–Hochberg FDR correction on the upper triangle. - Builds a signed adjacency matrix where only significant links are kept, with the sign indicating a concordant excess or deficit.
The validated projection is stored as:
T.graph # N × N signed adjacency matrix with entries in {-1, 0, 1}
Community Detection
SIBERIA provides community detection based on greedy minimization of:
BIC of a signed stochastic block model (
method="bic"), orFrustration of the signed network (
method="frustration").
communities = T.community_detection(
trials=500,
n_jobs=4,
method="bic", # or "frustration"
show=False,
random_state=42,
starter="uniform" # or "mixture"
)
This:
Runs multiple randomized greedy trials in parallel.
Minimizes the chosen objective for each trial.
Returns the best partition and stores it as:
T.communities # length-N array of community labels (0, 1, 2, …)
Graph and Community Plots
Plotting the Projection Matrix
Plot the projected signed adjacency matrix:
T.plot_graph(
export_path="results/adjacency", # saves results/adjacency_adjacency.pdf
show=True
)
This displays a heatmap with discrete values in {-1, 0, 1}.
Plotting Communities
Visualize the adjacency matrix reordered by detected communities, with blocks highlighted:
T.plot_communities(
export_path="results/communities", # saves results/communities_communities.pdf
show=True
)
This produces:
A reordered adjacency heatmap.
Lines separating communities, based on
T.communities.
Block Matrix of Community Structure
You can also inspect a coarse-grained block matrix summarizing dominant link signs between communities:
M = T.plot_block_matrix(
export_path="results/block_matrix", # saves results/block_matrix_block_matrix.pdf
show=True
)
M is a \(K \times K\) matrix (where \(K\) is the number of communities) with entries in {-1, 0, 1}, indicating whether positive or negative links dominate each intra- and inter-community block.
Documentation
You can find the complete documentation of the SIBERIA library at: https://siberia.readthedocs.io/en/latest/