Cross-Modal Coupling Analysis for PhysioExperiment Objects
PhysioCrossModal provides cross-modal coupling, connectivity, and synchrony analysis between physiological signals of different modalities (EEG, EMG, ECG, EDA, MoCap, fNIRS, etc.). It introduces the MultiPhysioExperiment container class for holding multiple PhysioExperiment objects at different sampling rates with temporal alignment. Its exported analysis surface supports spectral coherence, phase synchrony (PLV, PLI, wPLI), phase-amplitude coupling, directed coupling (Granger causality), time-domain coupling (cross-correlation), surrogate-based statistical testing, and publication-ready visualization.
You can install PhysioCrossModal from r-universe:
# the containers build on Bioconductor, so its repositories are needed too
install.packages("BiocManager", repos = "https://cloud.r-project.org")
install.packages("PhysioCrossModal",
repos = c("https://x-biosignal.r-universe.dev", BiocManager::repositories()))
Or install the development version from GitHub:
# install.packages("remotes", repos = "https://cloud.r-project.org")
remotes::install_github("x-biosignal/PhysioCrossModal")
library(PhysioCrossModal)
# Create simulated EEG + EMG data with known corticomuscular coupling
sim <- make_eeg_emg(
n_sec = 10,
sr_eeg = 500,
sr_emg = 1000,
cmc_freq = 20 # beta-band coupling
)
# Build a MultiPhysioExperiment from the two modalities
mpe <- MultiPhysioExperiment(
streams = list(EEG = sim$eeg, EMG = sim$emg)
)
# Inspect the container
mpe
modalities(mpe) # c("EEG", "EMG")
nModalities(mpe) # 2
samplingRates(mpe) # named vector of sampling rates
# Compute corticomuscular coherence between the two modalities
coh <- coherence(
mpe,
modality_x = "EEG",
modality_y = "EMG",
method = "welch"
)
# Peak coherence and the frequency at which it occurs
peak <- which.max(coh$coherence)
coh$frequencies[peak]
# Test statistical significance with phase-shuffled surrogates
sig <- surrogateTest(
mpe,
method = "coherence",
modality_x = "EEG",
modality_y = "EMG",
n_surrogates = 200
)
sig$p_value
The MultiPhysioExperiment S4 class is a container for multiple PhysioExperiment objects recorded at different sampling rates. It maintains temporal alignment metadata so that cross-modal analyses operate on correctly synchronized signals.
MultiPhysioExperiment(experiments, alignment)
experiments(), alignment(), modalities(), nModalities(), samplingRates()
mergePhysio() -- combine two MultiPhysioExperiment objects[ and [[ methods for extracting modalities by name or indexTemporal synchronization across modalities with different sampling rates:
alignSignals() -- align all modalities to a common time base using interpolationalignToRate() -- resample all modalities to a specified target sampling rateFrequency-domain coupling measures for identifying shared oscillatory activity:
coherence() -- magnitude-squared coherence between signal pairscoherenceMatrix() -- pairwise coherence across all channel combinationscrossSpectrum() -- complex-valued cross-spectral densitymultitaperCoherence() -- coherence estimated via multitaper spectral analysis (DPSS tapers)waveletCoherence() -- time-frequency coherence using continuous wavelet transformPhase-based coupling measures robust to amplitude variations:
phaseLockingValue() -- PLV for quantifying inter-trial or inter-signal phase consistencyphaseLagIndex() -- PLI, robust to volume conduction artifactsweightedPLI() -- wPLI, weighted variant with improved sensitivitywaveletPLV() -- time-resolved PLV using wavelet-extracted instantaneous phasephaseAmplitudeCoupling() -- one declared phase/amplitude band using Tort,
Canolty, Ozkurt, or PLV statisticscomodulogram() -- observed PAC across a phase-frequency by
amplitude-frequency gridmodulationIndex() -- strict Tort/Canolty/Ozkurt comodulogram with one
surrogate signal per complete grid, conservative cell-wise p-values, and
grid-wide multiplicity adjustmentPAC is an association, not evidence of a biological mechanism. Waveform shape, filter leakage and transients, non-stationarity, and common inputs can all produce high or significant values. Inspect the realized pass bands and the returned diagnostic strings before interpreting a significance mask.
Methods for inferring directional (causal) interactions between signals:
grangerCausality() -- parametric time/frequency-domain Granger causality
plus optional nonparametric Welch/DPSS estimation with Wilson spectral
factorization and frequency-resolved Geweke measuresGranger causality is a stationary linear predictive-direction measure. It does not establish physical or interventional causality and does not remove confounding, common-driver, volume-conduction, or instantaneous-mixing bias.
Coupling measures operating directly on the time series:
crossCorrelation() -- normalized cross-correlation with optimal lag estimationslidingCrossCorrelation() -- time-resolved cross-correlation in sliding windowsHigh-level wrappers that dispatch to specific coupling methods:
couplingAnalysis() -- compute any coupling measure via a single interface with method argumentcouplingMatrix() -- pairwise coupling matrix across all channel pairs for any supported methodNon-parametric significance testing and generalization assessment:
surrogateTest() -- phase-shuffled surrogate testing for a single coupling valuesurrogateMatrixTest() -- surrogate testing for full coupling matrices with multiple comparison correctionmodulationIndex() -- full-grid PAC surrogates with adjusted cell-wise
significancebootstrapCI() -- bootstrap confidence intervals for coupling estimateslodoGeneralization() -- leave-one-dataset-out cross-validation for assessing generalizability of coupling findings across datasets or subjectsPublication-ready plotting functions for coupling results:
plotCoherenceSpectrum() -- coherence as a function of frequency with significance thresholdplotCouplingMatrix() -- heatmap of pairwise coupling values across channelsplotCouplingTimecourse() -- time-resolved coupling (e.g., sliding cross-correlation or wavelet PLV)plotWaveletCoherence() -- time-frequency coherence scalogramplotComodulogram() -- PAC heatmap with optional significance attenuationHelper functions for generating test data with known coupling properties:
make_coupled_signals() -- two signals with controlled spectral couplingmake_directed_signals() -- signals with known causal (directed) relationshipmake_eeg_emg() -- realistic EEG and EMG pair with corticomuscular coherence| Application | Methods |
|---|---|
| Corticomuscular coherence (EEG-EMG) |
coherence(), multitaperCoherence()
|
| EEG inter-regional connectivity |
phaseLockingValue(), phaseLagIndex(), weightedPLI()
|
| Brain-heart coupling (EEG-ECG) |
crossCorrelation(), waveletCoherence()
|
| Neurovascular coupling (EEG-fNIRS) |
coherence(), grangerCausality()
|
| EDA-EMG sympathetic co-activation |
slidingCrossCorrelation(), couplingMatrix()
|
| Movement-brain synchrony (MoCap-EEG) |
waveletPLV(), waveletCoherence()
|
Optional (in Suggests):
PhysioCrossModal is part of the PhysioExperiment ecosystem, a suite of R packages for multi-modal physiological signal analysis:
| Package | Description |
|---|---|
| PhysioCore | Core data structures and accessors |
| PhysioIO | File I/O (EDF, HDF5, BIDS, CSV, MAT) |
| PhysioPreprocess | Preprocessing (filters, ICA, resampling) |
| PhysioAnalysis | Analysis and visualization |
| PhysioCrossModal | Cross-modal coupling and connectivity |
| PhysioMoCap | Motion capture and biomechanics |
Visit the r-universe page to browse all available packages.
MIT License. See LICENSE for details.
Yusuke Matsui
Part of the Physio ecosystem. Community and policy documents live in the umbrella repository: