Skip to main content

GyRAPH

A Python framework for signal processing on directed graphs.

Tests Coverage License: MIT Python 3.9+


Overview

GyRAPH provides graph shift operators for asymmetric graphs, a complex-valued Graph Fourier Transform built on their (possibly non-orthogonal) eigenbases, a family of filters that operate in the resulting spectral domain, and statistical tooling — surrogates and stationarity tests — for hypothesis testing on directed graph signals.

The library is built on NumPy, SciPy and NetworkX, and is designed to slot into existing analysis pipelines rather than replace them.

Key features

Area What you get
Graph shift operators Adjacency, directed Laplacian, advection–diffusion, and time–vertex (joint temporal/spatial) operators — each with normalization options and an automatic Jordan-block perturbation fallback for non-diagonalizable matrices.
Directed Graph Fourier Transform Forward and inverse GFT over complex eigenbases, conjugate-frequency pairing, and frequency ordering by eigenvalue magnitude.
Filters Spectral, polynomial (and dual-polynomial), Chebyshev, Faber, Hilbert, Tikhonov, and Wiener filters — including approximation schemes that avoid an explicit eigendecomposition.
Surrogates & stationarity Phase-randomized and structure-preserving surrogate generation, PSD estimation, and stationarity tests for null-hypothesis testing on graph signals.
Graph construction Synthetic generators (cycles, directed tori, asymmetric Erdős–Rényi, vortex and laminar-flow fields) and mesh/surface graphs (sphere, cube, bunny, dragon, hyperbolic paraboloid).
Metrics & visualization Dirichlet energy, total variation, Sobolev and directed-variation smoothness measures; publication-styled plotting for graphs, signals, spectra, meshes and dynamics.

Installation

pip install GyRAPH

From source, for development:

git clone https://github.com/miki998/GyRAPH.git && cd GyRAPH && pip install -e .

Requires Python 3.9+. Core dependencies (NumPy, SciPy, NetworkX, scikit-learn, pandas, matplotlib/seaborn/scienceplots, sympy, tqdm) are installed automatically; the mesh and learning-oriented modules additionally pull in PyTorch, torch-geometric, OpenCV and scikit-image.

Quickstart

Building a graph and its Fourier basis

import numpy as np
from gyraph.graphs import Graph, create_directed_torus

# A directed torus: 8 rows x 6 columns, asymmetric by construction
G, pos = create_directed_torus(Nr=8, Nc=6, directed=True)
graph = Graph(G=G, pos=pos)

# Attach a shift operator — this computes the Graph Fourier basis
graph.set_operator("adjacency")            # or "laplacian", "advection_diffusion", ...
op = graph.operator

print(graph)                                # active operator, node and edge counts
print(graph.is_directed(), graph.assymetry_level())
print(op.normality())                       # 0 if the operator is normal, larger otherwise
print(op.V[:5], op.frequencies[:5])         # eigenvalues and graph frequencies

set_operator accepts "adjacency", "laplacian", "advection_diffusion", "time_vertex_laplacian" and "time_vertex_adjacency", and forwards keyword arguments to the operator — e.g. graph.set_operator("laplacian", normalize="symmetric").

Transforming and filtering a signal

from gyraph.filters import SpectralFilter, PolynomialFilter

x = np.random.randn(graph.N)

# Graph Fourier Transform and its inverse
coef = op.GFT(x)
assert np.allclose(op.inverseGFT(coef), x)

# Low-pass in the spectral domain: keep the 10 lowest graph frequencies
kernel = np.zeros(graph.N)
kernel[:10] = 1.0

sfilt = SpectralFilter(graph)
x_low = sfilt.apply(x, kernel)

# Same response, approximated by a degree-K polynomial of the shift operator
# (no eigendecomposition needed at apply time)
pfilt = PolynomialFilter(graph, order=12)
x_low_approx = pfilt.apply(x, kernel)

For directed operators the spectrum is complex. SpectralFilter.transform_in_real enforces conjugate symmetry on a kernel so the filtered signal stays real-valued, and phase_shift generalizes the Hilbert transform to arbitrary phase rotations in the GFT domain.

Surrogates and stationarity testing

from gyraph.surrogates import Surrogate

surr = Surrogate(graph)

# 200 surrogates preserving the directed spectral structure of x
surrogates = surr.directed_random_surrogate(x, nrands=200, seed=99)

# Test whether a set of realizations is stationary w.r.t. the graph
is_stat = surr.is_stationary(surrogates, eps_diag=0.5, eps_mean=0.5, verbose=True)

Measuring signal smoothness

from gyraph.utils import dirichlet, TV, directed_variation

graph.set_operator("laplacian")
print(dirichlet(x, graph.operator.M))        # x^T L x
print(TV(x, graph.adj_matrix, norm="L1"))    # ||x - Ax||_1
print(directed_variation(x, graph.adj_matrix))

Package layout

gyraph/
├── graphs/        Graph container, synthetic generators, mesh & physical-flow graphs
├── operators/     Adjacency, Laplacian, advection–diffusion, time–vertex operators;
│                  Jordan-block and zero-eigenvalue handling
├── filters/       Spectral, polynomial, Chebyshev, Faber, Hilbert, Tikhonov, Wiener
├── surrogates/    Surrogate generation and stationarity/PSD estimation
├── stats/         p-values, circular statistics, complex Gaussian sampling
└── utils/         Numerics, smoothness metrics, plotting, logging configuration

Every subpackage is re-exported at the top level, so import gyraph gives access to gyraph.graphs, gyraph.filters, gyraph.operators, gyraph.surrogates and gyraph.utils. Importing gyraph also applies a publication-oriented matplotlib style (science/ieee) — see gyraph/constants.py if you would rather keep your own rcParams.

Examples and data

Runnable scripts and notebooks live in examples/ — start with examples/basic/ for graph construction, filtering and visualization, then move to examples/advanced/.

The data/ directory ships the graph datasets used throughout the examples and tests:

  • manhattan_graph_data/ — mid-Manhattan road network with NYC taxi flow signals
  • usa_graph_data/ — US state adjacency graph with boundary shapefiles
  • temperature_bretagne_graph_data/ — Brittany weather-station network

Development

pip install -e . && pip install pytest pytest-cov flake8 pre-commit && pre-commit install

Run the test suite (154 unit tests, ~84% line coverage):

python -m unittest discover -s tests/ -p 'test_*.py'

With coverage and linting, as CI does:

coverage run -m unittest discover -s tests/ -p 'test_*.py' && coverage report -m && flake8 . --max-line-length=127

Type checking is configured in mypy.ini. Both workflows — unit tests with a coverage badge, and packaging — run on every push to main (see .github/workflows/).

Contributions are welcome; please read CONTRIBUTING.md for the branch/commit conventions, NumPy-style docstring requirements and review process, and CODE_OF_CONDUCT.md before opening an issue or pull request.

Citation

If you use GyRAPH in academic work, please cite it. Machine-readable metadata is in CITATION.cff:

@software{chan_gyraph,
  author  = {Chan, Chun Hei Michael},
  title   = {{GyRAPH}: Directed Graph Signal Processing Framework},
  url     = {https://github.com/miki998/GyRAPH},
  license = {MIT}
}

Acknowledgment

This project has been partly funded by the Swiss National Science Foundation under Sinergia grant 209470 “Precision mapping of electrical brain network dynamics with application to epilepsy”.

License

Released under the MIT License. Copyright © Chun Hei Michael Chan, MIP:Lab, EPFL.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gyraph-1.0.0.tar.gz (14.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gyraph-1.0.0-py3-none-any.whl (87.4 kB view details)

Uploaded Python 3

File details

Details for the file gyraph-1.0.0.tar.gz.

File metadata

  • Download URL: gyraph-1.0.0.tar.gz
  • Upload date:
  • Size: 14.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.18

File hashes

Hashes for gyraph-1.0.0.tar.gz
Algorithm Hash digest
SHA256 afb74553e7aaddff24298190e09283446526728de1cc0b80f89f9169000f6c36
MD5 280bb0e41c572bf149f83bc7763cb6a1
BLAKE2b-256 47c10128c220be2cddc29b381c0adf913ed6cb5182af5f8d40546e2b35d71b9a

See more details on using hashes here.

File details

Details for the file gyraph-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: gyraph-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 87.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.18

File hashes

Hashes for gyraph-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1a19f517c1ce26187549f22ab64f7ea839c5bce040d1cd1e5b55535cd0d04141
MD5 045e70c9955be8a71861c1fb0ba5c005
BLAKE2b-256 4a38141c2a8277a12d453950b9cfb6674c597c84395ce3c49c5026a35b13860d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page