PhysioExperiment

The shared data model for physiological signal analysis.

Overview

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, PhysioPreprocess and PhysioAnalysis. 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.

Installation

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")

Quick Start

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.

Ecosystem

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())
)

Development

Rscript -e "devtools::test()"
R CMD build .
R CMD check PhysioExperiment_*.tar.gz

Citation

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

License

MIT © Yusuke Matsui

Governance and Support