Skip to content

MarsMDK/SIBERIA

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

78 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PyPI License:GPLv3 Python Version Paper

SIBERIA: SIgned BEnchmarks foR tIme series Analysis

SIBERIA provides maximum-entropy null models and validation methods for signed networks derived from time series.
Starting from an N × T matrix of standardized time series, it builds signed co-fluctuation signatures, fits maximum-entropy models, and produces validated signed graphs that can be analyzed via community detection.

The library implements advanced null models (bSRGM and bSCM, plus the naive projection) to distinguish meaningful mesoscale structure from noise, supporting reproducible and interpretable time-series network analysis.


Quick Start (Teaser)

Here is a minimal end-to-end example that generates synthetic data, fits a null model, validates signatures, builds a graph, and detects communities:

import numpy as np
from siberia import TSeries

# 1. Generate synthetic standardized time series (N nodes, T time steps)
N, Tlen = 50, 500
rng = np.random.default_rng(42)
data = rng.normal(size=(N, Tlen)).astype(float)

# 2. Initialize TSeries
T = TSeries(data=data, n_jobs=4)

# 3. Compute signature
T.compute_signature()

# 4. Fit a null model (bSCM with fixed-point solver)
T.fit(
    model="bSCM",
    maxiter=1000,
    max_nfev=1000,
    tol=1e-8,
    eps=1e-8,
    solver_type="fixed_point"
)

# 5. Predict event probabilities under the null model
T.predict()

# 6. Check signature distributions (ensemble vs analytical, KS score)
ks_score = T.check_distribution_signature(
    n_ensemble=500,
    ks_score=True,
    alpha=0.05
)
print("KS score:", ks_score)

# 7. Build a validated signed graph with FDR correction
graph = T.build_graph(
    fdr_correction_flag=True,
    alpha=0.05
)

# 8. Detect communities via signed SBM BIC minimization
communities = T.community_detection(
    trials=200,
    n_jobs=4,
    method="bic",
    show=False,
    random_state=42,
    starter="mixture"
)
print("Detected communities:", np.unique(communities))

# 9. Plot adjacency and community structure
T.plot_graph(export_path="results/adjacency", show=True)
T.plot_communities(export_path="results/communities", show=True)
T.plot_block_matrix(export_path="results/block_matrix", show=True)

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}, 
}

Contents


Installation

SIBERIA can be installed via pip. Run:

pip install siberia

To upgrade to the latest version:

pip install siberia --upgrade

Dependencies

SIBERIA requires the following libraries:

  • 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

Install them via:

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 × 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

Compute Signatures

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

Fit 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",          # 'bSRGM' or 'bSCM' or 'naive'
    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

Predict 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.

Check 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 via Monte Carlo sampling.
  • Computes analytical signature distributions (binomial / Poisson–Binomial) under the null model.
  • Performs KS tests pairwise and returns a normalized KS score in [0, 1], stored as:
T.ks_score
T.ensemble_signature        # N × N × n_ensemble
T.analytical_signature      # N × N × n_ensemble (or equivalent)
T.analytical_signature_dist # N × N × (T+1) PMFs for bSCM; analogous for bSRGM

A higher ks_score indicates better agreement between ensemble and analytical signatures at the chosen alpha threshold.

Build Graphs

From the empirical signature and the fitted model, you can construct a signed adjacency matrix using analytical p-values and (optionally) 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' and model='bSCM', SIBERIA:
    • Computes analytical p-values for concordant motifs under the fitted model.
    • Optionally applies Benjamini–Hochberg FDR correction on the upper triangle (fdr_correction_flag=True).
    • Builds a signed adjacency matrix where only significant links are kept, with sign indicating 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")
  • Frustration 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 × 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/

Credits

Authors:

Acknowledgments:

The module was developed under the supervision of
Tiziano Squartini,
Miguel Ibáñez Berganza, and
Tommaso Gili.

It was developed at the IMT School for Advanced Studies Lucca and Scuola Normale Superiore of Pisa.

This work is supported by the PNRR-M4C2-Investimento 1.3, Partenariato Esteso PE00000013 “FAIR–Future Artificial Intelligence Research” – Spoke 1 “Human-centered AI”, funded by the European Commission under the NextGeneration EU programme. MDV also acknowledges support by the European Community programme under the funding scheme ERC-2018-ADG G.A. 834756 “XAI: Science and technology for the eXplanation of AI decision making”.

About

Siberia provides maximum-entropy null models and validation methods for signed networks derived from time series. It enables the construction, filtering, and community detection of signed adjacency matrices based on validated co-fluctuations.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages