The shared data model for physiological signal analysis.
PhysioExperiment provides the data structures the x-biosignal R ecosystem is built on. Domain packages apply specialised methods to these shared containers.
| Container | Holds |
|---|---|
PhysioExperiment |
one recording: all assays, time and channel annotation, events, provenance |
MultiPhysioExperiment |
several streams recorded together, each at its own rate, on one shared clock |
PhysioLongitudinal |
repeated sessions of one subject, with their conditions and time points |
PhysioCohort |
several subjects, with their subject-level data |
Within one recording, repeated trials are recorded as intervals
(trials(), trialIntervals()), extracted with trial(), and aggregated with
aggregateTrials(), which keeps partial trials out of an average unless asked.
streamCoverage() reports what a span actually covers, so a trial that contains
a gap is stored as the fact it is and refused only by the operations that need
continuous data.
It depends on no other Physio* package, so it can be installed and used on its
own.
Moving from an earlier version. This package used to be an umbrella that attached
PhysioCore,PhysioIO,PhysioPreprocessandPhysioAnalysis. That role now belongs to PhysioEcosystem, which also provides the GUI and REST launchers.library(PhysioCore)still works and re-exports this package unchanged. See the migration guide for details.
The containers build on Bioconductor, so its repositories have to be on the list
as well -- without them the install stops at SummarizedExperiment.
install.packages("BiocManager", repos = "https://cloud.r-project.org")
install.packages(
"PhysioExperiment",
repos = c("https://x-biosignal.r-universe.dev", BiocManager::repositories())
)
For the whole stack -- I/O, preprocessing, analysis and the GUI/REST launchers -- install the umbrella instead:
install.packages("BiocManager", repos = "https://cloud.r-project.org")
install.packages(
"PhysioEcosystem",
repos = c("https://x-biosignal.r-universe.dev", BiocManager::repositories())
)
The development snapshot can also be installed from GitHub:
install.packages("remotes", repos = "https://cloud.r-project.org")
remotes::install_github("x-biosignal/PhysioExperiment")
This package provides the containers and the operations on them. Everything here
runs with PhysioExperiment alone.
library(PhysioExperiment)
set.seed(42)
eeg <- matrix(rnorm(1000 * 4), nrow = 1000, ncol = 4)
colnames(eeg) <- c("Fz", "Cz", "Pz", "Oz")
pe <- PhysioExperiment(
assays = list(raw = eeg),
colData = S4Vectors::DataFrame(label = colnames(eeg), type = rep("EEG", 4)),
samplingRate = 250
)
samplingRate(pe)
channelNames(pe)
duration(pe)
Several streams recorded together, each keeping its own rate, on one shared clock. Nothing is resampled by holding them:
emg <- PhysioExperiment(
assays = list(raw = matrix(rnorm(4000 * 2), 4000, 2)),
samplingRate = 1000
)
mpe <- MultiPhysioExperiment(
streams = list(eeg = pe, emg = emg),
offsets = c(eeg = 0, emg = 0.137) # the EMG started 137 ms later
)
streamRates(mpe)
commonClock(mpe)$offsets
# select a span by the samples' real time on the shared clock
win <- timeWindow(mpe, 1.0, 2.0)
vapply(streamTimeIndex(win), function(t) t[1], numeric(1))
Trials inside a recording are stored as intervals and extracted by the same rules:
trials(mpe) <- data.frame(subject_id = "P1", session_id = "S1",
trial_id = c("T1", "T2"), observed = TRUE)
trialIntervals(mpe) <- data.frame(
subject_id = "P1", session_id = "S1", trial_id = c("T1", "T2"),
recording_id = "R1", stream = "eeg",
start = c(0.0, 2.0), end = c(1.5, 3.5)
)
trialCoverage(mpe, "T1") # what each stream actually covers
t1 <- trial(mpe, "T1")
streamNames(t1)
Filtering, spectra, connectivity, I/O and the GUI live in the domain packages —
butterworthFilter() in PhysioPreprocess, fftSignals() and bandPower() in
PhysioAnalysis, launchGUI() in PhysioEcosystem. Install
PhysioEcosystem to get them all
under one library() call; its README has the corresponding examples.
Each package is maintained in its own public repository and can be installed independently from x-biosignal r-universe.
| Package | Scope |
|---|---|
| PhysioExperiment | The shared data model: containers, clock, events, provenance, trials |
| PhysioEcosystem | Umbrella interface and GUI/REST launchers |
| PhysioCore | Compatibility layer re-exporting PhysioExperiment |
| PhysioIO | File and database input/output |
| PhysioPreprocess | Signal preprocessing |
| PhysioAnalysis | Analysis and visualization |
| PhysioEEG | EEG analysis |
| PhysioEMG | EMG and muscle synergy analysis |
| PhysioECG | ECG and heart-rate variability |
| PhysioEDA | Electrodermal activity |
| PhysioNIRS | Near-infrared spectroscopy and SNIRF |
| PhysioHDEMG | High-density surface EMG decomposition |
| PhysioNeurophys | TMS and motor neurophysiology |
| PhysioCrossModal | Cross-modal coupling |
| PhysioMoCap | Motion capture and biomechanics |
| PhysioOpenSim | OpenSim integration |
| PhysioMSKNet | Musculoskeletal network analysis |
| PhysioGaitNorm | Normative gait references |
| PhysioHeadModels | EEG head models and forward solvers |
| PhysioDevices | Wearable and laboratory device ingestion |
| PhysioWearable | Free-living accelerometry |
| PhysioStream | Governed real-time streams |
| PhysioML | Leakage-aware machine learning |
| PhysioTrial | Trial randomization and blinding |
| PhysioClinStats | Clinical inference |
| PhysioClinical | Clinical outcomes and responder analysis |
| PhysioCompliance | Evidence, privacy, and lifecycle controls |
| PhysioReport | Clinical report generation |
| PhysioAnnotationHub | Anatomical and clinical knowledge graph |
Install a focused package with the same repository configuration:
install.packages(
c("PhysioEEG", "PhysioNIRS", "PhysioClinical"),
repos = c("https://x-biosignal.r-universe.dev", BiocManager::repositories())
)
Rscript -e "devtools::test()"
R CMD build .
R CMD check PhysioExperiment_*.tar.gz
@software{matsui2026physioexperiment,
author = {Yusuke Matsui},
title = {{PhysioExperiment}: Unified Analysis of Physiological Signals in {R}},
year = {2026},
url = {https://github.com/x-biosignal/PhysioExperiment},
version = {1.0.0}
}
MIT © Yusuke Matsui