PyGPLA is a Python package for analyzing multichannel spike–field coupling using Generalized Phase Locking Analysis (GPLA) as introduced in:
Safavi et al. (2023), Uncovering the organization of neural circuits with Generalized Phase Locking Analysis, PLOS Computational Biology.
GPLA summarizes high-dimensional spike–Local Field Potential (LFP) coupling by constructing a complex coupling matrix and computing its dominant low-rank structure via Singular Value Decomposition (SVD). The output includes:
- a scalar coupling strength (gPLV)
- an LFP vector and spike vector whose magnitudes/phases are interpretable at the population level
- optional significance testing (analytical RMT-based or spike-jitter surrogates)
- GPLA core: coupling matrix construction + SVD + phase convention
- Statistical testing:
- fast RMT-based heuristic (Marchenko–Pastur edge)
- spike-jitter surrogate tests (interval / ISI-preserved / group-preserved / population)
- Data preparation: trial concatenation, spike-count filtering, temporal/unit selection, and optional PCA whitening of user-provided analytic LFP signals
- Simulations: phase-locked and transient coupling generators
- Figure reproduction: a Figure 2-style simulation and visualization script
pip install pygplagit clone https://github.com/CMC-lab/PyGPLA.git
cd PyGPLA
pip install -e .# SciPy (for simulations and real-data style filtering/Hilbert workflows)
pip install -e ".[sim]"
# Documentation build (Sphinx + MyST)
pip install -e ".[docs]"
# Tests
pip install -e ".[tests]"This minimal example simulates transiently coupled spikes and an analytic LFP signal, then
runs GPLA via pygpla.api.gpla.
import numpy as np
from pygpla.api import gpla
from pygpla.simulations import simulate_transient_locked
rng = np.random.default_rng(123)
signal_params = dict(nCh=1, nUnit=12, SF=600.0, nTr=6, signalLength=6.0)
global_params = dict(
oscFreq=20.0,
nCycl=15,
syncSigProportion=0.7,
lfpPhaseNoise_kappa=8.0,
whiteNoise_sigma=0.05,
)
spike_params = dict(avefiringRate=18.0)
coupling_params = dict(lockingStrength_kappa=10.0, lockingPhase=0.0)
lfp_real, lfp_analytic, spikes, meta = simulate_transient_locked(
global_params,
spike_params,
coupling_params,
signal_params,
return_analytic=True,
rng=rng,
)
result = gpla(
spikes,
lfp_analytic, # shape: (channels, samples, trials), complex dtype
stats_config=None, # or {"testType": "RMT-based"} / spike-jitter config
plvNrmlzMethed="var1_theoretical",
flag_whitening=0,
flag_lfpNrmlz=0,
)
print("gPLV:", result.gplv)
print("LFP vector shape:", result.lfp_vector.shape)
print("Spike vector shape:", result.spike_vector.shape)Input conventions:
- spike trains: list of trials, each
(n_units, n_samples) - preferred LFP input:
(n_channels, n_samples, n_trials)complex analytic array - supported alternative: a real array of phase angles in radians
gpla()does not treat real-valued input as raw LFP voltage. Raw LFP data must be band-pass filtered and converted to an analytic signal upstream, for example with a Hilbert transform. If a real array is passed, PyGPLA warns that it will be interpreted as phase angles in radians.
Install the extras it needs (SciPy for filtering, Matplotlib for plotting), then run:
pip install -e ".[sim,figures]"
python paper/figures/figure2.pyThis generates paper/figures/figure2_python.png (plus PDF/SVG/EPS exports).
Build the docs locally:
pip install -e ".[docs]"
sphinx-build -b html docs docs/_build/htmlStart reading at docs/_build/html/index.html.
pip install -e ".[tests]"
pytestIf you use PyGPLA in your research, please cite the following papers.
The original GPLA method paper:
Safavi, S., Panagiotaropoulos, T. I., Kapoor, V., Ramirez-Villegas, J. F., Logothetis, N. K., & Besserve, M. (2023). Uncovering the organization of neural circuits with Generalized Phase Locking Analysis. PLOS Computational Biology, 19(4), e1010983.
@article{safavi2023uncovering,
title = {Uncovering the organization of neural circuits with Generalized Phase Locking Analysis},
author = {Safavi, Shervin and Panagiotaropoulos, Theofanis I. and Kapoor, Vishal and Ramirez-Villegas, Juan F. and Logothetis, Nikos K. and Besserve, Michel},
journal = {PLoS Computational Biology},
year = {2023},
volume = {19},
number = {4},
pages = {e1010983},
doi = {10.1371/journal.pcbi.1010983}
}The mathematical framework underlying GPLA's coupling measure and its Random Matrix Theory–based significance test:
Safavi, S., Logothetis, N. K., & Besserve, M. (2021). From Univariate to Multivariate Coupling Between Continuous Signals and Point Processes: A Mathematical Framework. Neural Computation, 33(7), 1751–1817.
@article{safavi2021univariate,
title = {From Univariate to Multivariate Coupling Between Continuous Signals and Point Processes: A Mathematical Framework},
author = {Safavi, Shervin and Logothetis, Nikos K. and Besserve, Michel},
journal = {Neural Computation},
year = {2021},
volume = {33},
number = {7},
pages = {1751--1817},
doi = {10.1162/neco_a_01389}
}BSD 2-Clause License. See LICENSE.
Developed at the CMC-Lab.
- Maintainer: Amir Khani — i.khani.amir@gmail.com