| Title: | Shared Data Model for Physiological Signal Analysis |
|---|---|
| Description: | Provides the shared data model for the Physio ecosystem: the PhysioExperiment class, a 'SummarizedExperiment' extension for multi-modal physiological signal data (such as electroencephalography, electromyography, and electrocardiography), together with the containers for multiple simultaneously recorded streams, repeated sessions of one subject, and cohorts of subjects. Includes core accessors, channel and event management, provenance, and basic 'S4' methods. Domain packages apply specialized methods to these shared containers and are installed separately. |
| Authors: | Yusuke Matsui [aut, cre] |
| Maintainer: | Yusuke Matsui <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 2.3.1 |
| Built: | 2026-10-03 13:42:11 UTC |
| Source: | https://github.com/x-biosignal/PhysioExperiment |
x[c(start, end), streams] is shorthand for
timeWindow(x, start, end, streams).
## S4 method for signature 'MultiPhysioExperiment,ANY,ANY,ANY' x[i, j, ..., drop = FALSE]## S4 method for signature 'MultiPhysioExperiment,ANY,ANY,ANY' x[i, j, ..., drop = FALSE]
x |
A |
i |
Numeric vector of length 2: |
j |
Character vector of stream names. |
... |
Ignored. |
drop |
Ignored; present for signature compatibility. |
This is the former PhysioCrossModal [ method. Its meaning is
preserved, with one deliberate correction: the old implementation computed
indices as floor(t * rate) + 1 from the rate alone, which ignored each
stream's start offset and could admit one sample lying before start.
Selection is now made on each sample's actual time on the shared clock. For
windows whose bounds land on sample times - including all zero-offset data
with grid-aligned bounds - the selection is unchanged.
A MultiPhysioExperiment.
Extracts a subset of the PhysioExperiment by row (time) and/or
column (channel) indices, preserving metadata and appending a processing-history
entry with the supplied indices and input/output dimensions. Missing indices
select the full corresponding axis.
## S4 method for signature 'PhysioExperiment,ANY,ANY,ANY' x[i, j, ..., drop = FALSE]## S4 method for signature 'PhysioExperiment,ANY,ANY,ANY' x[i, j, ..., drop = FALSE]
x |
A PhysioExperiment object. |
i |
Time indices (rows). |
j |
Channel indices (columns in first non-time dimension). |
... |
Additional arguments (not used). |
drop |
Logical. If TRUE, drops dimensions of size 1. |
A PhysioExperiment object containing only the selected
time points and/or channels, with updated rowData and colData.
Huber, W., et al. (2015). "Orchestrating high-throughput genomic analysis with Bioconductor." Nature Methods, 12(2), 115-121. doi:10.1038/nmeth.3252
Morgan, M., et al. (2022). "S4Vectors: Foundation of vector-like and list-like containers in Bioconductor." R package.
extractWindow for subsetting by time in seconds,
pickChannels for subsetting by channel name,
dropChannels for removing specific channels
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) # Subset by time pe_subset <- pe[1:50, ] dim(pe_subset) # 50 4 # Subset by channels pe_channels <- pe[, 1:2] dim(pe_channels) # 100 2pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) # Subset by time pe_subset <- pe[1:50, ] dim(pe_subset) # 50 4 # Subset by channels pe_channels <- pe[, 1:2] dim(pe_channels) # 100 2
Add events to a PhysioExperiment object
addEvents(x, onset, duration = 0, type = "event", value = "")addEvents(x, onset, duration = 0, type = "event", value = "")
x |
A PhysioExperiment object. |
onset |
Numeric vector of event onset times in seconds. |
duration |
Numeric vector of event durations in seconds. |
type |
Character vector of event types. |
value |
Character vector of event values/labels. |
The modified PhysioExperiment object.
Delorme A, Makeig S (2004). "EEGLAB: an open source toolbox for analysis of single-trial EEG dynamics." Journal of Neuroscience Methods, 134(1), 9-21.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
setEvents for replacing all events,
removeEvents for removing events,
getEvents for retrieving events,
nEvents for event count
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 100)), samplingRate = 100 ) # Add stimulus events pe <- addEvents(pe, onset = c(1, 2, 3), type = "stimulus") # Add response events pe <- addEvents(pe, onset = c(1.5, 2.5), type = "response", value = c("hit", "hit")) nEvents(pe) # 5 events totalpe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 100)), samplingRate = 100 ) # Add stimulus events pe <- addEvents(pe, onset = c(1, 2, 3), type = "stimulus") # Add response events pe <- addEvents(pe, onset = c(1.5, 2.5), type = "response", value = c("hit", "hit")) nEvents(pe) # 5 events total
A thin convenience over logStep that records an append-only
provenance entry on the object's metadata log (never dropping prior entries),
optionally capturing an integer seed in the entry parameters so the
step is reproducible under a fixed seed.
addProvenance( pe, step, params = list(), seed = NULL, package = NA_character_, version = NA_character_ )addProvenance( pe, step, params = list(), seed = NULL, package = NA_character_, version = NA_character_ )
pe |
A |
step |
Character step / activity name. |
params |
Named list of parameters recorded with the step. |
seed |
Optional integer seed captured in the entry parameters. |
package, version
|
Optional producing-package name and version. |
pe with the entry appended to its provenance log.
pe <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) pe <- addProvenance(pe, "conformalInterval", seed = 42) provenance(pe)pe <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) pe <- addProvenance(pe, "conformalInterval", seed = 42) provenance(pe)
Appends a session and re-sorts the container into chronological order by
days_from_baseline.
addSession( x, label, pe, days_from_baseline, condition = NA_character_, session_id = label )addSession( x, label, pe, days_from_baseline, condition = NA_character_, session_id = label )
x |
A |
label |
The visit label (e.g. |
pe |
A |
days_from_baseline |
Numeric days since the baseline visit. |
condition |
Optional condition string. |
session_id |
Session id (defaults to |
The updated PhysioLongitudinal, re-sorted chronologically.
Add a subject to a PhysioCohort
addSubject(x, id, subject, group = NA_character_, meta = list())addSubject(x, id, subject, group = NA_character_, meta = list())
x |
A |
id |
The new subject's id (must be unique). |
subject |
A |
group |
Optional group/arm label for the new subject. |
meta |
Optional named list of extra subject-level colData values. |
The updated PhysioCohort.
Summarizes scalar features while preserving observation identity. Higher targets are reached one level at a time: cycles to trials, trials to sessions, sessions to subjects, and subjects to a cohort. With the default mean, each immediate child receives equal weight, regardless of how many observations contributed to that child. These are descriptive summaries, not models or estimates of sampling uncertainty.
aggregatePhysioFeatures( x, level, features = NULL, strata = NULL, FUN = mean, na.rm = FALSE, ... )aggregatePhysioFeatures( x, level, features = NULL, strata = NULL, FUN = mean, na.rm = FALSE, ... )
x |
A nonempty data.frame or S4Vectors DataFrame of features, or an
unmodified result of this function or |
level |
Required target: |
features |
Names of numeric scalar feature columns, required for a new table. Inherited when continuing a previous aggregation result. |
strata |
Additional columns to keep separate at every level, such as
|
FUN |
Function, or function name, reducing a nonempty numeric vector to
one finite numeric value. Defaults to |
na.rm |
Logical. Missing features cause an error by default. If TRUE, omit missing children separately for each feature; an all-missing group is retained with NA. Infinite values always cause an error. |
... |
Additional arguments to FUN. Weight vectors tied to original rows are not supported: vector lengths change at successive levels. |
Repeated session/trial names in different parents remain distinct. Duplicate full observation keys, including strata, are rejected. Identifiers are normalized to character. Group order follows first appearance in the input.
To give trials equal weight, the mean of a session with trial means 1 and 9 is 5 even if the trials contain different numbers of cycles. Requesting a subject or cohort directly performs the same intervening steps as chaining results with the same FUN and arguments. For nonlinear FUN, this is a nested summary (e.g. a median of trial medians), not a pooled summary. Custom functions should be deterministic and depend only on their supplied inputs; recorded function text does not capture external state or closure values.
Features must have compatible units and meaning within each group; this function cannot infer those from numeric columns. It does not align or average raw waveforms, construct trial containers, infer missing IDs, or establish statistical independence. Absent trials are not counted; only supplied rows and their missing feature values can be audited.
For a modality returned by PhysioMoCap's summarizeCycleFeatures(), combine
its key table and feature block with cbind(z$keys$emg, z$blocks$emg) and
specify the feature names and strata = "side". Different modalities can
be summarized separately using the same hierarchy and strata.
A physio_aggregation list with data (one row per target unit and
stratum), features, strata, level, source (the retained original
input table), and source_rows (a list mapping each output row to rows of
source, including rows with missing features). steps records each reached
level's data, source mapping, method text, arguments and missing-value policy.
Each step's counts has output-row and feature identifiers, n_units
(immediate children), n_used, n_missing, and n_source (mapped original
rows, not an effective sample size). counts also exposes the final step.
A checksum detects changed data or lineage before further aggregation.
cycles <- data.frame(subject_id = "person1", session_id = "session1", trial_id = c("trial1", "trial1", "trial2"), cycle_id = c("cycle1", "cycle2", "cycle1"), amplitude = c(0, 2, 9)) trials <- aggregatePhysioFeatures(cycles, "trial", "amplitude") sessions <- aggregatePhysioFeatures(trials, "session") sessions$data # mean(c(1, 9)) = 5 sessions$counts # two trials, three original cycles aggregatePhysioFeatures(cycles, "session", "amplitude")$datacycles <- data.frame(subject_id = "person1", session_id = "session1", trial_id = c("trial1", "trial1", "trial2"), cycle_id = c("cycle1", "cycle2", "cycle1"), amplitude = c(0, 2, 9)) trials <- aggregatePhysioFeatures(cycles, "trial", "amplitude") sessions <- aggregatePhysioFeatures(trials, "session") sessions$data # mean(c(1, 9)) = 5 sessions$counts # two trials, three original cycles aggregatePhysioFeatures(cycles, "session", "amplitude")$data
Selects rows from the trial table and hands them to
aggregatePhysioFeatures. The aggregation itself - the equal
weighting of immediate children at each level, the link back to source rows,
the checksum - is unchanged: choosing which trials take part is a selection of
input rows, not a reweighting.
aggregateTrials( x, level, features = NULL, include = "complete", rule = "nominal", gap_factor = 1.5, ... )aggregateTrials( x, level, features = NULL, include = "complete", rule = "nominal", gap_factor = 1.5, ... )
x |
A |
level |
Target level, passed to |
features |
Feature column names on the trial table. |
include |
Which states take part: any of |
rule, gap_factor
|
Passed to |
... |
Passed to |
Each trial is classified before anything is averaged, because averaging a truncated trial together with whole ones silently mixes different amounts of evidence:
"complete"Every stream the trial names covers it fully.
"partial"A stream covers less of the interval than it asks
for. The interval was cut by a window, or it runs past the end of the
recording, or streamCoverage reports a dropout inside it.
"unknown"Completeness cannot be decided here. Coverage is
undecidable; or a gap an earlier window recorded cannot be re-derived under
this query's rate or gap_factor, so the dropout can be neither
confirmed nor ruled out; or the stream holds more samples in the interval
than its declared rate predicts – nothing is missing, but the grid does not
describe it. None of these is the same as complete.
"undescribed"No interval is recorded for the trial, so
nothing describes its extent. Excluded by default: a trial table of
per-trial values with no intervals is a job for
aggregatePhysioFeatures directly, or ask for
include = "undescribed" here.
Every judgement comes from streamCoverage – the shortfall, the
dropout it reports, and what it says it could not re-derive – so a trial is
excluded by the same rule that reports the problem rather than by a second
definition of it.
The states are decided in that order: shown to be short, then unable to tell,
then shown to be whole. Losing the evidence for a gap therefore never promotes
a trial to "complete" – a question that can no longer be answered is not
an answer of yes – while a shortfall this query can still demonstrate outranks
a record it cannot reuse.
A list with aggregate (the aggregation result), counts
(one entry per state plus n_included / n_excluded),
states (the state of every trial) and excluded.
aggregatePhysioFeatures, trialIntervals,
streamCoverage
Evaluates one stream on an explicitly supplied trial-relative grid, then averages trials, sessions and subjects with equal weight at each level. Measured sample times take priority over reconstructed sampling times.
aggregateTrialWaveforms( x, stream, grid, align = c("start", "phase"), level = c("session", "subject", "cohort"), assay = "raw", channels = NULL, strata = NULL, anchors = NULL, include = "complete", gap_factor = 1.5, na.rm = FALSE )aggregateTrialWaveforms( x, stream, grid, align = c("start", "phase"), level = c("session", "subject", "cohort"), assay = "raw", channels = NULL, strata = NULL, anchors = NULL, include = "complete", gap_factor = 1.5, na.rm = FALSE )
x |
A |
stream |
One stream name, evaluated separately from other modalities. |
grid |
Finite, strictly increasing evaluation points. For |
align |
Either |
level |
Target: |
assay |
Name of the two-dimensional numeric signal assay. |
channels |
Unique channel names. By default all channels are used and their sets must agree across included recordings. Column order may differ. |
strata |
Trial-table columns, such as condition, kept separate at every aggregation level. Modalities and channels are never averaged together. |
anchors |
Optional data frame with subject_id, session_id, trial_id, start and end, keyed uniquely by the first three columns. Times use each recording's local shared clock. Without this table, the union of all stream intervals defines each trial's anchors, preserving inter-stream offsets. Windowed inputs require explicit anchors: a cropped boundary is not an original trial onset. A supplied start may also be an event alignment time. |
include |
Trial states to include: |
gap_factor |
Gap criterion passed to |
na.rm |
If FALSE, any unavailable aligned value causes an error. TRUE omits it pointwise; an all-missing group is retained with mean NA and zero contributing trials. This can change contributing units along the waveform. |
Linear interpolation uses adjacent finite samples inside the selected stream's trial interval. There is no extrapolation, interpolation across reported gaps, or skipping over missing signal values. Exact samples at gap boundaries remain usable. Included trials with unusable retained gap evidence are refused. The output is an interpolated representation, not antialias filtering; preprocess signals appropriately before choosing a coarser grid.
Channel names establish correspondence, not compatible units or physiology. The caller must provide comparable assays and units. Source hashes include times, selected signal values, channel metadata and interval/trial tables. Interpolation indices refer to rows in the input recording, including when that recording was previously windowed. Inputs themselves are not modified.
aggregatePhysioFeatures performs the hierarchy and preserves
intermediate results and source-row links. The waveform SD or a confidence
interval is not estimated: trials are not treated as independent participants.
A list with data (mean waveform by output unit, channel and
grid point), counts (immediate-child counts and n_trials, the
number of finite contributing original trial values), aggregate
(the full hierarchical result), aligned (selected trial values),
sample_map (record, stream, channel, bracketing original row indices,
interpolation weight and missingness reason for each aligned row),
trials (all trial states and selections), anchors,
settings, source hashes, and a result checksum.
aggregateTrials, streamTimeIndex
pe <- PhysioExperiment(assays = list(raw = matrix(0:30, ncol = 1, dimnames = list(NULL, "signal"))), samplingRate = 10) m <- MultiPhysioExperiment(sensor = pe) trials(m) <- data.frame(subject_id = "P1", session_id = "S1", trial_id = c("T1", "T2")) trialIntervals(m) <- data.frame(trials(m)[1:3], recording_id = "R1", stream = "sensor", start = c(0, 2), end = c(1, 3)) z <- aggregateTrialWaveforms(m, "sensor", grid = c(0, 0.5, 1)) z$data z$countspe <- PhysioExperiment(assays = list(raw = matrix(0:30, ncol = 1, dimnames = list(NULL, "signal"))), samplingRate = 10) m <- MultiPhysioExperiment(sensor = pe) trials(m) <- data.frame(subject_id = "P1", session_id = "S1", trial_id = c("T1", "T2")) trialIntervals(m) <- data.frame(trials(m)[1:3], recording_id = "R1", stream = "sensor", start = c(0, 2), end = c(1, 3)) z <- aggregateTrialWaveforms(m, "sensor", grid = c(0, 0.5, 1)) z$data z$counts
Convenience wrapper for resampleToCommon(x, reference_rate) using the
shared clock's reference rate.
alignStreams(x)alignStreams(x)
x |
A |
A single-rate PhysioExperiment.
Construct an AnalysisResult
AnalysisResult( type, result = list(), parameters = list(), provenance = data.frame(), estimate = NULL, uncertainty = list(), method = NA_character_, estimand = list() )AnalysisResult( type, result = list(), parameters = list(), provenance = data.frame(), estimate = NULL, uncertainty = list(), method = NA_character_, estimand = list() )
type |
Character analysis tag. |
result |
Named list payload. |
parameters |
Named list of parameters. |
provenance |
Optional lineage |
estimate |
Optional point estimate carried by the result. |
uncertainty |
Optional named list describing the interval (with a
|
method |
Optional character estimation-method label. |
estimand |
Optional named list of ICH E9(R1) estimand attributes. |
An AnalysisResult object.
AnalysisResult("hrv_time", result = list(sdnn = 42, rmssd = 30)) AnalysisResult("rom", estimate = 118, uncertainty = list(type = "conformal", level = 0.9, lower = 104, upper = 132), estimand = list(population = "post-op knee", summary_measure = "median"))AnalysisResult("hrv_time", result = list(sdnn = 42, rmssd = 30)) AnalysisResult("rom", estimate = 118, uncertainty = list(type = "conformal", level = 0.9, lower = 104, upper = 132), estimand = list(population = "post-op knee", summary_measure = "median"))
Accessors for analysis results
resultType(x) ## S4 method for signature 'AnalysisResult' resultType(x) resultValue(x) ## S4 method for signature 'AnalysisResult' resultValue(x) ## S4 method for signature 'PhysioBiomarker' resultValue(x) biomarkerValue(x) ## S4 method for signature 'PhysioBiomarker' biomarkerValue(x)resultType(x) ## S4 method for signature 'AnalysisResult' resultType(x) resultValue(x) ## S4 method for signature 'AnalysisResult' resultValue(x) ## S4 method for signature 'PhysioBiomarker' resultValue(x) biomarkerValue(x) ## S4 method for signature 'PhysioBiomarker' biomarkerValue(x)
x |
An |
resultType() the type tag; resultValue() the payload
(or scalar value for a biomarker); biomarkerValue() the scalar value.
res <- AnalysisResult("hrv_time", result = list(sdnn = 42, rmssd = 30)) resultType(res) resultValue(res) bm <- PhysioBiomarker("SDNN", 42, unit = "ms") biomarkerValue(bm)res <- AnalysisResult("hrv_time", result = list(sdnn = 42, rmssd = 30)) resultType(res) resultValue(res) bm <- PhysioBiomarker("SDNN", 42, unit = "ms") biomarkerValue(bm)
Estimand / uncertainty carrier accessors
estimateOf(x) ## S4 method for signature 'AnalysisResult' estimateOf(x) uncertaintyOf(x) ## S4 method for signature 'AnalysisResult' uncertaintyOf(x) provenanceOf(x) ## S4 method for signature 'AnalysisResult' provenanceOf(x) estimandOf(x) ## S4 method for signature 'AnalysisResult' estimandOf(x)estimateOf(x) ## S4 method for signature 'AnalysisResult' estimateOf(x) uncertaintyOf(x) ## S4 method for signature 'AnalysisResult' uncertaintyOf(x) provenanceOf(x) ## S4 method for signature 'AnalysisResult' provenanceOf(x) estimandOf(x) ## S4 method for signature 'AnalysisResult' estimandOf(x)
x |
An |
estimateOf() the point estimate; uncertaintyOf() the
interval list; provenanceOf() the provenance; estimandOf() the
ICH E9(R1) estimand list.
r <- AnalysisResult("rom", estimate = 118, uncertainty = list(type = "conformal", level = 0.9, lower = 104, upper = 132)) estimateOf(r) uncertaintyOf(r)r <- AnalysisResult("rom", estimate = 118, uncertainty = list(type = "conformal", level = 0.9, lower = 104, upper = 132)) estimateOf(r) uncertaintyOf(r)
A lightweight S4 container so every analysis (HRV, synergies, gait indices, ...) returns a consistently-shaped object that reporting and downstream code can consume uniformly.
## S4 method for signature 'AnalysisResult' show(object)## S4 method for signature 'AnalysisResult' show(object)
object |
An object to display. |
The show methods return NULL invisibly and are called
for the side effect of printing a compact summary.
typeCharacter tag identifying the analysis (e.g. "hrv_time").
resultNamed list holding the payload.
parametersNamed list of parameters used to produce the result.
provenanceOptional data.frame lineage (see provenance).
estimateThe point estimate the result carries (any type).
uncertaintyNamed list describing the interval, with a type in
none, conformal, bayes, bootstrap, ncp or analytic,
plus (typically) level, lower and upper.
methodCharacter label of the estimation method.
estimandNamed list of ICH E9(R1) estimand attributes (population, treatment, endpoint / variable, summary measure, intercurrent-event handling).
Appends one PROV activity to the object's audit trail. Two forms are supported: a high-level form that builds a full PROV-O record from named fields, and a low-level form that appends a pre-built entry list.
appendProvenance( x, entry = NULL, activity = NULL, params = list(), input_assay = NA_character_, output_assay = NA_character_, agent = NA_character_, software_version = NA_character_, package = NA_character_ )appendProvenance( x, entry = NULL, activity = NULL, params = list(), input_assay = NA_character_, output_assay = NA_character_, agent = NA_character_, software_version = NA_character_, package = NA_character_ )
x |
A |
entry |
Either a pre-built entry |
activity |
Character scalar naming the PROV activity (the operation). |
params |
Named list of parameters to record. |
input_assay, output_assay
|
The assay(s) the activity used / generated
(PROV |
agent |
The responsible agent (defaults to |
software_version, package
|
Software agent name and version. |
x with the activity appended to its provenance log.
pe <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) pe <- appendProvenance(pe, activity = "filterSignals", params = list(low = 1, high = 40), input_assay = "raw", output_assay = "filtered") provenance(pe)$activitype <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) pe <- appendProvenance(pe, activity = "filterSignals", params = list(low = 1, high = 40), input_assay = "raw", output_assay = "filtered") provenance(pe)$activity
Applies a standard electrode montage (e.g., 10-20 system).
applyMontage(x, system = c("10-20", "10-10", "10-5"))applyMontage(x, system = c("10-20", "10-10", "10-5"))
x |
A PhysioExperiment object. |
system |
Montage system: "10-20", "10-10", or "10-5". |
Modified PhysioExperiment object with electrode positions.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
setElectrodePositions for custom positions,
getElectrodePositions for reading positions,
channelNames for channel labels,
setReference for reference electrode
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) # Apply 10-20 system positions pe <- applyMontage(pe, "10-20") getElectrodePositions(pe)pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) # Apply 10-20 system positions pe <- applyMontage(pe, "10-20") getElectrodePositions(pe)
Converts the default assay of a PhysioExperiment to a
data.frame with a time column (in seconds) followed by
one column per channel.
## S4 method for signature 'PhysioExperiment' as.data.frame(x, row.names = NULL, optional = FALSE, ...)## S4 method for signature 'PhysioExperiment' as.data.frame(x, row.names = NULL, optional = FALSE, ...)
x |
A PhysioExperiment object. |
row.names |
Unused. |
optional |
Unused. |
... |
Additional arguments. |
A data.frame with a time column and one column per
channel. For 3D arrays, only the first sample (third dimension index 1)
is returned. Returns an empty data.frame if no assays are present.
Huber, W., et al. (2015). "Orchestrating high-throughput genomic analysis with Bioconductor." Nature Methods, 12(2), 115-121. doi:10.1038/nmeth.3252
Morgan, M., et al. (2022). "S4Vectors: Foundation of vector-like and list-like containers in Bioconductor." R package.
summary,PhysioExperiment-method for summary statistics,
timeIndex for the time vector,
channelNames for column names
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(12), nrow = 3, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) df <- as.data.frame(pe) head(df)pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(12), nrow = 3, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) df <- as.data.frame(pe) head(df)
Flattens every field - value, unit, CI, reference range, reliability (ICC/SEM/MDC), and provenance (assay/band/method/software version) - into a single row so biomarkers tabulate and round-trip losslessly.
## S3 method for class 'PhysioBiomarker' as.data.frame(x, row.names = NULL, optional = FALSE, ...)## S3 method for class 'PhysioBiomarker' as.data.frame(x, row.names = NULL, optional = FALSE, ...)
x |
|
row.names |
Optional row names passed to |
optional |
Ignored; present for S3 generic compatibility. |
... |
Ignored. |
A one-row data.frame with the flattened fields.
Builds the per-visit metric matrix and wraps it as an
MSKLongitudinalTracker (its activation_series), so
PhysioMSKNet's mskMinimalDetectableChange() and
mskRecoveryTrajectoryFit() can consume the container output directly
(metrics play the role of "muscles", visits the role of timepoints).
asMSKTracker(long, metric_fn, metric_name = "metric")asMSKTracker(long, metric_fn, metric_name = "metric")
long |
A |
metric_fn, metric_name
|
As in |
An object of class "MSKLongitudinalTracker" carrying the
metric-by-visit matrix.
mk <- function(m) PhysioExperiment( S4Vectors::SimpleList(raw = matrix(m, 10, 2)), samplingRate = 100) pl <- PhysioLongitudinal(baseline = mk(1), mid = mk(2), discharge = mk(3)) tr <- asMSKTracker(pl, function(e) mean(SummarizedExperiment::assay(e, "raw"))) dim(tr$activation_series)mk <- function(m) PhysioExperiment( S4Vectors::SimpleList(raw = matrix(m, 10, 2)), samplingRate = 100) pl <- PhysioLongitudinal(baseline = mk(1), mid = mk(2), discharge = mk(3)) tr <- asMSKTracker(pl, function(e) mean(SummarizedExperiment::assay(e, "raw"))) dim(tr$activation_series)
Requires the MultiAssayExperiment package. Each session becomes an
experiment (named by session_id); the design schema and subject
metadata are stored in the result's metadata().
asMultiAssayExperiment(x)asMultiAssayExperiment(x)
x |
A |
A MultiAssayExperiment.
Returns the sampling rate associated with each assay of a
PhysioExperiment. If no per-assay rates have been recorded, all assays
are assumed to share the object's main samplingRate.
assaySamplingRates(x)assaySamplingRates(x)
x |
A |
For genuinely multi-rate acquisitions (streams of different length) prefer the
MultiRatePhysioExperiment container; assaySamplingRates()
is the lightweight per-assay tag for single-object, equal-length assays.
A named numeric vector of sampling rates (Hz), one per assay.
Crochiere, R. E. & Rabiner, L. R. (1983). Multirate Digital Signal Processing. Prentice Hall.
setAssaySamplingRate,
MultiRatePhysioExperiment
pe <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) assaySamplingRates(pe)pe <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) assaySamplingRates(pe)
Performs a Bland-Altman analysis comparing two measurement methods or two time points. Computes the bias (mean difference), limits of agreement, and confidence interval for the bias.
blandAltman(x, y, confidence = 0.95)blandAltman(x, y, confidence = 0.95)
x |
Numeric vector of measurements from method/time 1. |
y |
Numeric vector of measurements from method/time 2. |
confidence |
Numeric; confidence level for limits of agreement (default 0.95). |
The Bland-Altman method assesses agreement between two measurements by plotting their difference against their mean. The limits of agreement are:
where is the mean difference (bias) and is the
SD of differences.
A list with components:
Mean difference (x - y)
Lower limit of agreement
Upper limit of agreement
Standard deviation of differences
Two-element vector with lower and upper CI for the bias
Bland JM, Altman DG (1986). Statistical methods for assessing agreement between two methods of clinical measurement. Lancet, 327(8476), 307-310.
icc() for intraclass correlation reliability analysis,
benchmarkAgreement() for benchmark validation agreement metrics, and
plotBlandAltman() in the PhysioMoCap package to visualize the agreement.
set.seed(42) method1 <- rnorm(30, mean = 50, sd = 10) method2 <- method1 + rnorm(30, mean = 0, sd = 3) result <- blandAltman(method1, method2) result$bias result$lower_loa result$upper_loaset.seed(42) method1 <- rnorm(30, mean = 50, sd = 10) method2 <- method1 + rnorm(30, mean = 0, sd = 3) result <- blandAltman(method1, method2) result$bias result$lower_loa result$upper_loa
Combines two PhysioExperiment objects by concatenating along the channel (column) dimension. Both objects must have the same number of time points and matching sampling rates.
cbindPhysio(x, y)cbindPhysio(x, y)
x |
A PhysioExperiment object. |
y |
A PhysioExperiment object to combine. |
A PhysioExperiment object with channels from both x
and y, combined colData, and metadata from x.
Huber, W., et al. (2015). "Orchestrating high-throughput genomic analysis with Bioconductor." Nature Methods, 12(2), 115-121. doi:10.1038/nmeth.3252
Morgan, M., et al. (2022). "S4Vectors: Foundation of vector-like and list-like containers in Bioconductor." R package.
rbindPhysio for combining along the time axis,
pickChannels for selecting specific channels,
dropChannels for removing channels
pe1 <- PhysioExperiment( assays = list(raw = matrix(rnorm(200), nrow = 100, ncol = 2)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz")), samplingRate = 100 ) pe2 <- PhysioExperiment( assays = list(raw = matrix(rnorm(200), nrow = 100, ncol = 2)), colData = S4Vectors::DataFrame(label = c("Pz", "Oz")), samplingRate = 100 ) # Combine channels pe_combined <- cbindPhysio(pe1, pe2) nChannels(pe_combined) # 4pe1 <- PhysioExperiment( assays = list(raw = matrix(rnorm(200), nrow = 100, ncol = 2)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz")), samplingRate = 100 ) pe2 <- PhysioExperiment( assays = list(raw = matrix(rnorm(200), nrow = 100, ncol = 2)), colData = S4Vectors::DataFrame(label = c("Pz", "Oz")), samplingRate = 100 ) # Combine channels pe_combined <- cbindPhysio(pe1, pe2) nChannels(pe_combined) # 4
Applies a user metric to every session of a PhysioLongitudinal
and reports each visit's change from the baseline visit, optionally flagged
against a minimal-detectable-change (MDC) threshold.
changeScores( long, metric_fn, baseline = NULL, method = c("absolute", "percent", "z"), mdc = NULL, metric_name = "metric" )changeScores( long, metric_fn, baseline = NULL, method = c("absolute", "percent", "z"), mdc = NULL, metric_name = "metric" )
long |
A |
metric_fn |
A function taking one session (a |
baseline |
The baseline visit label or session id. If |
method |
Delta reported: |
mdc |
Optional MDC threshold: a numeric scalar (applied to all metrics),
a numeric vector named by metric, or a vector matching the metric count.
The |
metric_name |
Name used for the metric when |
A tidy DataFrame with columns subject, visit,
days_from_baseline, metric, value,
delta_from_baseline, exceeds_mdc.
Beckerman, H., et al. (2001). Smallest real difference, a link between reproducibility and responsiveness. Quality of Life Research, 10(7), 571-578.
asMSKTracker, PhysioLongitudinal
mk <- function(m) PhysioExperiment( S4Vectors::SimpleList(raw = matrix(m, 10, 2)), samplingRate = 100) pl <- PhysioLongitudinal( baseline = mk(1), discharge = mk(3), design = S4Vectors::DataFrame( session_id = c("baseline", "discharge"), visit_label = c("baseline", "discharge"), days_from_baseline = c(0, 42))) changeScores(pl, function(e) mean(SummarizedExperiment::assay(e, "raw")))mk <- function(m) PhysioExperiment( S4Vectors::SimpleList(raw = matrix(m, 10, 2)), samplingRate = 100) pl <- PhysioLongitudinal( baseline = mk(1), discharge = mk(3), design = S4Vectors::DataFrame( session_id = c("baseline", "discharge"), visit_label = c("baseline", "discharge"), days_from_baseline = c(0, 42))) changeScores(pl, function(e) mean(SummarizedExperiment::assay(e, "raw")))
Functions for managing channel metadata including labels, types, units, and electrode positions. Get channel information
channelInfo(x)channelInfo(x)
x |
A PhysioExperiment object. |
Returns channel metadata as a DataFrame. Channel information is stored in colData (columns = channels).
A DataFrame with channel information.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
channelNames for channel labels,
nChannels for channel count,
setChannelTypes for assigning channel types
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame( label = c("Fz", "Cz", "Pz", "Oz"), type = rep("EEG", 4) ), samplingRate = 100 ) # Get channel information channelInfo(pe) # Get channel names channelNames(pe) # Get number of channels nChannels(pe)pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame( label = c("Fz", "Cz", "Pz", "Oz"), type = rep("EEG", 4) ), samplingRate = 100 ) # Get channel information channelInfo(pe) # Get channel names channelNames(pe) # Get number of channels nChannels(pe)
Updates channel metadata. Channel information is stored in colData (columns = channels).
channelInfo(x) <- valuechannelInfo(x) <- value
x |
A PhysioExperiment object. |
value |
A DataFrame with channel information. |
Modified PhysioExperiment object.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
channelInfo for reading channel metadata,
channelNames for channel labels,
setChannelTypes for assigning channel types
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) # Set channel info channelInfo(pe) <- S4Vectors::DataFrame( label = c("Fz", "Cz", "Pz", "Oz"), type = rep("EEG", 4) )pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) # Set channel info channelInfo(pe) <- S4Vectors::DataFrame( label = c("Fz", "Cz", "Pz", "Oz"), type = rep("EEG", 4) )
Get channel names/labels
channelNames(x)channelNames(x)
x |
A PhysioExperiment object. |
Character vector of channel names.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
channelInfo for full channel metadata,
renameChannels for renaming channels,
nChannels for channel count
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) channelNames(pe) # c("Fz", "Cz", "Pz", "Oz")pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) channelNames(pe) # c("Fz", "Cz", "Pz", "Oz")
Set channel names/labels
channelNames(x) <- valuechannelNames(x) <- value
x |
A PhysioExperiment object. |
value |
Character vector of channel names. |
Modified PhysioExperiment object.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
channelNames for reading channel labels,
renameChannels for renaming specific channels,
channelInfo for full channel metadata
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) channelNames(pe) <- c("Fz", "Cz", "Pz", "Oz") channelNames(pe)pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) channelNames(pe) <- c("Fz", "Cz", "Pz", "Oz") channelNames(pe)
Validates assay data for NA values and reports statistics.
checkNA(x, action = c("warn", "error", "none"))checkNA(x, action = c("warn", "error", "none"))
x |
A PhysioExperiment object or numeric array. |
action |
Action to take: "warn" (default), "error", or "none". |
Invisibly returns a list with NA statistics.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
hasNA for quick NA presence check,
naSummary for per-assay NA statistics,
handleNA for NA replacement strategies
pe <- PhysioExperiment( assays = list(raw = matrix(c(1, NA, 3, 4), nrow = 2)), samplingRate = 100 ) checkNA(pe)pe <- PhysioExperiment( assays = list(raw = matrix(c(1, NA, 3, 4), nrow = 2)), samplingRate = 100 ) checkNA(pe)
The association between an angular variable (e.g. a coupling angle or relative phase) and a linear one (e.g. speed, force, a clinical score). Symmetric under rotation of the angle.
circularLinearCorrelation(theta, x, units = c("degrees", "radians"))circularLinearCorrelation(theta, x, units = c("degrees", "radians"))
theta |
Numeric angular variable. |
x |
Numeric linear variable (same length as |
units |
|
an htest: the circular-linear correlation r (estimate), the test
statistic n * r^2 ~ chi-square(2) and its p.value.
Mardia KV (1976); Zar JH (1999) eq. 27.19.
set.seed(3); th <- runif(60, 0, 360); y <- cos(th * pi / 180) + rnorm(60, 0, 0.3) circularLinearCorrelation(th, y)$estimate # strong associationset.seed(3); th <- runif(60, 0, 360); y <- cos(th * pi / 180) + rnorm(60, 0, 0.3) circularLinearCorrelation(th, y)$estimate # strong association
The mean direction of a set of angles and its circular spread, computed via the resultant vector (so the wrap-around at 0/360 is handled correctly).
circularSummary(angles, units = c("degrees", "radians"))circularSummary(angles, units = c("degrees", "radians"))
angles |
Numeric vector of angles. |
units |
|
a circular_summary list: mean (mean direction), R (resultant
length), rbar (mean resultant length in [0,1]), variance
(1 - rbar), sd (circular SD), kappa (von Mises concentration), all in
the input units where applicable.
Zar JH (1999) Biostatistical Analysis, ch. 26-27.
rayleighTest(), circularLinearCorrelation()
circularSummary(c(10, 20, 350, 355))$mean # ~ 0, not ~180circularSummary(c(10, 20, 350, 355))$mean # ~ 0, not ~180
Computes Cohen's d effect size for comparing two groups or conditions, with confidence intervals and qualitative interpretation.
cohensD(x, y, paired = FALSE, pooled = TRUE)cohensD(x, y, paired = FALSE, pooled = TRUE)
x |
Numeric vector for group 1 (or condition 1 if paired). |
y |
Numeric vector for group 2 (or condition 2 if paired). |
paired |
Logical; if TRUE, computes effect size for paired data using the SD of differences as the denominator. |
pooled |
Logical; if TRUE (default), uses pooled SD as denominator.
If FALSE, uses the SD of |
For independent groups with pooled = TRUE, the pooled SD is:
For paired data, the denominator is the SD of the within-pair differences.
Interpretation thresholds follow Cohen (1988):
|d| < 0.2: negligible
0.2 <= |d| < 0.5: small
0.5 <= |d| < 0.8: medium
|d| >= 0.8: large
A list with components:
Cohen's d value
Lower bound of 95 percent confidence interval
Upper bound of 95 percent confidence interval
Qualitative label: "negligible", "small", "medium", or "large"
Cohen J (1988). Statistical Power Analysis for the Behavioral Sciences. Lawrence Erlbaum Associates.
etaSquared() for ANOVA-based effect sizes,
plotEffectSizeForest() for forest plot visualization of effect sizes.
set.seed(42) x <- rnorm(30, mean = 10, sd = 2) y <- rnorm(30, mean = 8, sd = 2) result <- cohensD(x, y) result$d result$interpretationset.seed(42) x <- rnorm(30, mean = 10, sd = 2) y <- rnorm(30, mean = 8, sd = 2) result <- cohensD(x, y) result$d result$interpretation
Subject-level metadata table of a PhysioCohort
cohortData(x) ## S4 method for signature 'PhysioCohort' cohortData(x) cohortData(x) <- value ## S4 replacement method for signature 'PhysioCohort' cohortData(x) <- valuecohortData(x) ## S4 method for signature 'PhysioCohort' cohortData(x) cohortData(x) <- value ## S4 replacement method for signature 'PhysioCohort' cohortData(x) <- value
x |
A |
value |
A subject-level |
cohortData() the subject-level DataFrame.
Flattens the whole cohort into one tidy data.frame with a row per
(subject, session): subject_id, any subject-level colData (e.g.
group), and the session's session_id, visit_label,
days_from_baseline and condition. This is the iteration unit for
pipelines, longitudinal models and trial analyses.
cohortDesign(x)cohortDesign(x)
x |
A |
A data.frame, one row per subject-session.
Lists the trials of every subject, carrying both the subject and the session.
The same trial_id under two subjects has to stay distinguishable, which
is why the subject travels with the row rather than being inferred.
cohortTrials(x)cohortTrials(x)
x |
A |
A data frame of trials with subject and session columns.
The shared clock
commonClock(x)commonClock(x)
x |
A |
The clock list (t0, reference_rate, offsets,
offsets_assumed, schema).
Returns the name of the first assay in the PhysioExperiment object,
which is treated as the default assay for operations that do not specify
an assay explicitly.
defaultAssay(x)defaultAssay(x)
x |
A |
Character scalar naming the first assay, or NA_character_
when no assays are present.
Huber, W., et al. (2015). "Orchestrating high-throughput genomic analysis with Bioconductor." Nature Methods, 12(2), 115-121. doi:10.1038/nmeth.3252
Morgan, M., et al. (2022). "S4Vectors: Foundation of vector-like and list-like containers in Bioconductor." R package.
PhysioExperiment for the constructor,
samplingRate for the sampling rate accessor,
timeIndex for time point vector
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(100), nrow = 10), filtered = matrix(0, 10, 10)), samplingRate = 250 ) defaultAssay(pe)pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(100), nrow = 10), filtered = matrix(0, 10, 10)), samplingRate = 250 ) defaultAssay(pe)
deprecate_physio( when, what, with = NULL, details = NULL, severity = c("warn", "stop"), id = NULL )deprecate_physio( when, what, with = NULL, details = NULL, severity = c("warn", "stop"), id = NULL )
when |
Version string in which the deprecation was introduced, e.g.
|
what |
String naming the deprecated function or argument, e.g.
|
with |
Optional string naming the replacement, e.g. |
details |
Optional character vector of extra guidance shown to the user. |
severity |
|
id |
Optional deprecation id used to de-duplicate warnings within a
session; ignored when |
A thin, ecosystem-wide wrapper over lifecycle::deprecate_warn() and
lifecycle::deprecate_stop() so every Physio package signals deprecations the
same way. Use severity = "warn" during the deprecation window and switch to
severity = "stop" once the item is defunct. See the ecosystem
DEPRECATION.md policy for the lifecycle stages and the minimum window.
Called for its side effect (a warning or an error); invisibly returns
NULL.
lifecycle::deprecate_warn(), lifecycle::deprecate_stop()
old_fn <- function(x) { deprecate_physio("0.3.0", "old_fn()", with = "new_fn()") x } # Warnings are shown once per session by default; force them for testing with # options(lifecycle_verbosity = "warning").old_fn <- function(x) { deprecate_physio("0.3.0", "old_fn()", with = "new_fn()") x } # Warnings are shown once per session by default; force them for testing with # options(lifecycle_verbosity = "warning").
A method for the BiocGenerics design generic, so it composes
cleanly with the rest of the Bioconductor ecosystem.
## S4 method for signature 'PhysioLongitudinal' design(object, ...) ## S4 replacement method for signature 'PhysioLongitudinal' design(object, ...) <- value## S4 method for signature 'PhysioLongitudinal' design(object, ...) ## S4 replacement method for signature 'PhysioLongitudinal' design(object, ...) <- value
object |
A |
... |
Ignored. |
value |
A design |
design() the design DataFrame.
A step between consecutive sample times larger than gap_factor times the
nominal period counts as a gap. The factor is an adopted criterion – it
separates acquisition jitter from a dropped sample; it does not prove that no
gap exists – and it is the same criterion PhysioCrossModal uses to refuse
interpolating across one.
detectGaps(times, rate, gap_factor = 1.5, window = NULL, tolerance = NULL)detectGaps(times, rate, gap_factor = 1.5, window = NULL, tolerance = NULL)
times |
Sample times in seconds, ascending. |
rate |
Nominal sampling rate in Hz. |
gap_factor |
Multiple of the nominal period above which a step counts as a gap. |
window |
Optional |
tolerance |
Overlap tolerance; defaults to the tolerance
|
Detection runs on the whole series before any window is applied, and the window then selects which gaps to report. Selecting samples first and differencing afterwards loses exactly the gaps that matter most: a dropout straddling a window's edge has one of its two bounding samples outside the window, so the step across it is never formed and the window looks intact.
A gap that only touches an endpoint of the window is not in it. On a closed
interval the two share a single instant, and the recording does cover that
instant – the same reading of "touching is not overlapping" that
trialIntervals uses.
A data frame of start and end – the sample times the gap
lies between, in the original series, not clipped to window.
detectGaps(c(0, 0.1, 0.2, 0.4, 0.5), rate = 10) # the same gap, found from a window whose edge cuts through it detectGaps(c(0, 0.1, 0.2, 0.4, 0.5), rate = 10, window = c(0.25, 0.45))detectGaps(c(0, 0.1, 0.2, 0.4, 0.5), rate = 10) # the same gap, found from a window whose edge cuts through it detectGaps(c(0, 0.1, 0.2, 0.4, 0.5), rate = 10, window = c(0.25, 0.45))
Returns the dimensions of the default assay.
## S4 method for signature 'PhysioExperiment' dim(x)## S4 method for signature 'PhysioExperiment' dim(x)
x |
A PhysioExperiment object. |
An integer vector of dimensions (time points by channels
by samples for 3D data),
or NULL if no assays are present.
Huber, W., et al. (2015). "Orchestrating high-throughput genomic analysis with Bioconductor." Nature Methods, 12(2), 115-121. doi:10.1038/nmeth.3252
Morgan, M., et al. (2022). "S4Vectors: Foundation of vector-like and list-like containers in Bioconductor." R package.
length,PhysioExperiment-method for time point count,
nChannels for channel count,
defaultAssay for the assay being queried
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) dim(pe) # 100 4pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) dim(pe) # 100 4
Creates a new PhysioExperiment without specified channels.
dropChannels(x, channels)dropChannels(x, channels)
x |
A PhysioExperiment object. |
channels |
Integer indices or character names of channels to drop. |
A new PhysioExperiment without specified channels.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
pickChannels for keeping specific channels,
getChannelsByType for finding channels by type,
nChannels for channel count
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) # Drop by index pe_dropped <- dropChannels(pe, 1) nChannels(pe_dropped) # 3 # Drop by name pe_dropped <- dropChannels(pe, c("Fz", "Oz"))pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) # Drop by index pe_dropped <- dropChannels(pe, 1) nChannels(pe_dropped) # 3 # Drop by name pe_dropped <- dropChannels(pe, c("Fz", "Oz"))
Computes the total duration of the signal in seconds from the number of time points and the sampling rate.
duration(x)duration(x)
x |
A PhysioExperiment object. |
Numeric scalar giving the signal duration in seconds, or
NA_real_ if the sampling rate is not set.
Huber, W., et al. (2015). "Orchestrating high-throughput genomic analysis with Bioconductor." Nature Methods, 12(2), 115-121. doi:10.1038/nmeth.3252
Morgan, M., et al. (2022). "S4Vectors: Foundation of vector-like and list-like containers in Bioconductor." R package.
samplingRate for the sampling rate,
length,PhysioExperiment-method for time point count,
timeIndex for the time vector,
extractWindow for time-based subsetting
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 1000, ncol = 4)), samplingRate = 100 ) duration(pe) # 10 secondspe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 1000, ncol = 4)), samplingRate = 100 ) duration(pe) # 10 seconds
Returns the seconds between the starts of two independently recorded trials.
elapsedBetweenTrials(x, from, to)elapsedBetweenTrials(x, from, to)
x |
A |
from, to
|
Trial identifiers. |
This is refused unless the recordings are actually placed relative to one
another. Declaring time_correspondence = "measured" is not enough: the
rows must also carry a reference and an offset, and both trials
must be measured against the same reference, since offsets on different
references are not comparable. "order_only" and "unknown" are
refused outright - the order in which recordings were made is not a duration,
and turning one into the other would fabricate a measurement.
An absent absolute origin (clock$t0 of NA) is a different matter
and does not block this: what is needed is the correspondence between
recordings, not an absolute time.
Numeric seconds from from to to.
Computes eta-squared, partial eta-squared, and omega-squared from a one-way between-subjects comparison.
etaSquared(x, groups)etaSquared(x, groups)
x |
Numeric vector of values. |
groups |
Factor or character vector of group membership. |
Eta-squared is the proportion of total variance explained by group membership:
Omega-squared provides a less biased estimate:
For one-way designs, partial eta-squared equals eta-squared.
A list with components:
Eta-squared (SS_between / SS_total)
Partial eta-squared (SS_between / (SS_between + SS_within))
Omega-squared (bias-corrected effect size)
Cohen J (1988). "Statistical Power Analysis for the Behavioral Sciences." Lawrence Erlbaum Associates.
cohensD() for pairwise effect sizes,
plotEffectSizeForest() for forest plot visualization.
set.seed(42) x <- c(rnorm(20, 10, 2), rnorm(20, 12, 2), rnorm(20, 14, 2)) groups <- rep(c("A", "B", "C"), each = 20) result <- etaSquared(x, groups) result$eta_sqset.seed(42) x <- c(rnorm(20, 10, 2), rnorm(20, 12, 2), rnorm(20, 14, 2)) groups <- rep(c("A", "B", "C"), each = 20) result <- etaSquared(x, groups) result$eta_sq
Create an EventQuery from a PhysioExperiment
eventQuery(x)eventQuery(x)
x |
A PhysioExperiment object |
An EventQuery object
pe <- PhysioExperiment(assays = list(raw = matrix(rnorm(400), 100, 4)), samplingRate = 100) pe <- addEvents(pe, onset = c(1, 2, 3), type = "stimulus") q <- eventQuery(pe)pe <- PhysioExperiment(assays = list(raw = matrix(rnorm(400), 100, 4)), samplingRate = 100) pe <- addEvents(pe, onset = c(1, 2, 3), type = "stimulus") q <- eventQuery(pe)
EventQuery class for composable event filtering
sourcePhysioExperiment object
filtersList of filter functions to apply
resolvedCached resolved events (NULL if not yet resolved)
Applies named feature functions to each selected trial and channel. Accepts
the same recording and hierarchy inputs as aggregateTrialWaveforms().
Trial selection, time-based sample selection, channel matching and assembly
of the feature table are performed together. Pass the returned object to
aggregatePhysioFeatures() to obtain session, subject or cohort summaries.
extractTrialFeatures( x, stream, FUN, assay = "raw", channels = NULL, strata = NULL, include = "complete", gap_factor = 1.5, ... )extractTrialFeatures( x, stream, FUN, assay = "raw", channels = NULL, strata = NULL, include = "complete", gap_factor = 1.5, ... )
x |
A |
stream |
Name of the stream to measure. |
FUN |
Named, nonempty list of feature functions, for example
|
assay |
Assay name, default |
channels |
Channel names. Defaults to all channels, requiring the same names across selected recordings; column order may differ. |
strata |
Trial-table columns to preserve as separate groups in subsequent aggregation. Channels are always kept separate. |
include |
Trial states to process: |
gap_factor |
Gap criterion passed to |
... |
Additional fixed arguments passed to every feature function. |
Sample membership uses the measured time index and the same boundary tolerance
as timeWindow(). Samples are neither interpolated nor resampled. For
explicitly included partial trials, features describe the available samples
inside the retained interval; these can differ in duration between trials.
Included trials with unusable retained gap evidence are refused. Trials
lacking the requested stream or interval are recorded as excluded. A recording
without a trial table, ambiguous identity, an incompatible assay/channel set,
an empty selected interval, or a failed feature function causes an error.
Temporal coverage does not establish signal quality. Missing values are passed
to the feature function; returned NA values remain in the table and
require explicit handling when aggregating. Infinite input samples and
infinite feature results are rejected. Feature-function text and supplied
arguments are recorded, but arbitrary external state used by a callback is
not captured; use self-contained functions and explicit arguments.
Correspondence is established by channel names. Comparable units and feature definitions remain the caller's responsibility. The returned checksum detects modification of the extraction result before aggregation, and references are preserved when continuing aggregation through further levels.
A physio_trial_features list containing data (one row per
selected trial and channel), trials (all trial selections and reasons),
source_map (one entry per feature-table row: recording, interval,
original sample indices and sample times), source_hashes (full input
recording hashes), features, strata, settings and
checksum. Input containers are not modified.
aggregatePhysioFeatures, aggregateTrials,
aggregateTrialWaveforms
pe <- PhysioExperiment(assays = list(raw = matrix(0:30, ncol = 1, dimnames = list(NULL, "signal"))), samplingRate = 10) m <- MultiPhysioExperiment(sensor = pe) trials(m) <- data.frame(subject_id = "P1", session_id = "S1", trial_id = c("T1", "T2")) trialIntervals(m) <- data.frame(trials(m)[1:3], recording_id = "R1", stream = "sensor", start = c(0, 2), end = c(1, 3)) f <- extractTrialFeatures(m, "sensor", FUN = list(amplitude = mean)) f$data aggregatePhysioFeatures(f, "session")$data # mean(c(5, 25)) = 15pe <- PhysioExperiment(assays = list(raw = matrix(0:30, ncol = 1, dimnames = list(NULL, "signal"))), samplingRate = 10) m <- MultiPhysioExperiment(sensor = pe) trials(m) <- data.frame(subject_id = "P1", session_id = "S1", trial_id = c("T1", "T2")) trialIntervals(m) <- data.frame(trials(m)[1:3], recording_id = "R1", stream = "sensor", start = c(0, 2), end = c(1, 3)) f <- extractTrialFeatures(m, "sensor", FUN = list(amplitude = mean)) f$data aggregatePhysioFeatures(f, "session")$data # mean(c(5, 25)) = 15
Extracts a time window from the signal based on start and end times in seconds.
extractWindow(x, tmin, tmax)extractWindow(x, tmin, tmax)
x |
A PhysioExperiment object. |
tmin |
Start time in seconds. |
tmax |
End time in seconds. |
A PhysioExperiment object containing only the samples
within the specified time window, with preserved channel and event
metadata.
Huber, W., et al. (2015). "Orchestrating high-throughput genomic analysis with Bioconductor." Nature Methods, 12(2), 115-121. doi:10.1038/nmeth.3252
Morgan, M., et al. (2022). "S4Vectors: Foundation of vector-like and list-like containers in Bioconductor." R package.
duration for total signal duration,
timeIndex for the time vector,
[ forindex-based subsetting,
timeToSamples for converting times to indices
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 1000, ncol = 4)), samplingRate = 100 ) # Extract 2 to 5 seconds pe_window <- extractWindow(pe, tmin = 2, tmax = 5) duration(pe_window) # approximately 3 secondspe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 1000, ncol = 4)), samplingRate = 100 ) # Extract 2 to 5 seconds pe_window <- extractWindow(pe, tmin = 2, tmax = 5) duration(pe_window) # approximately 3 seconds
Fills NA values at the beginning and end of a signal that may result from filtering operations.
fillEdgeNA(x, method = c("extend", "zero"))fillEdgeNA(x, method = c("extend", "zero"))
x |
Numeric vector. |
method |
Fill method: "extend" (extend nearest valid value) or "zero" (fill with zeros). |
Vector with edge NA values filled.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
handleNA for general NA handling strategies,
replaceNA for NA handling in PhysioExperiment assays
x <- c(NA, NA, 1, 2, 3, NA, NA) fillEdgeNA(x, method = "extend")x <- c(NA, NA, 1, 2, 3, NA, NA) fillEdgeNA(x, method = "extend")
Filter events by type
filterType(q, types)filterType(q, types)
q |
An EventQuery object |
types |
Character vector of event types to keep |
Modified EventQuery
pe <- PhysioExperiment(assays = list(raw = matrix(rnorm(400), 100, 4)), samplingRate = 100) pe <- addEvents(pe, onset = c(1, 2, 3), type = c("stimulus", "response", "stimulus")) q <- filterType(eventQuery(pe), "stimulus") resolveQuery(q)pe <- PhysioExperiment(assays = list(raw = matrix(rnorm(400), 100, 4)), samplingRate = 100) pe <- addEvents(pe, onset = c(1, 2, 3), type = c("stimulus", "response", "stimulus")) q <- filterType(eventQuery(pe), "stimulus") resolveQuery(q)
Filter events by value
filterValue(q, values)filterValue(q, values)
q |
An EventQuery object |
values |
Character vector of event values to keep |
Modified EventQuery
pe <- PhysioExperiment(assays = list(raw = matrix(rnorm(400), 100, 4)), samplingRate = 100) pe <- addEvents(pe, onset = c(1, 2, 3), type = "stimulus", value = c("target", "distractor", "target")) q <- filterValue(eventQuery(pe), "target") resolveQuery(q)pe <- PhysioExperiment(assays = list(raw = matrix(rnorm(400), 100, 4)), samplingRate = 100) pe <- addEvents(pe, onset = c(1, 2, 3), type = "stimulus", value = c("target", "distractor", "target")) q <- filterValue(eventQuery(pe), "target") resolveQuery(q)
Format a PhysioBiomarker as a compact string
## S3 method for class 'PhysioBiomarker' format(x, ...)## S3 method for class 'PhysioBiomarker' format(x, ...)
x |
|
... |
Ignored. |
A length-1 character string "name = value unit [ci]".
Functions for functional data analysis including functional PCA (fPCA), functional regression, and curve registration. These methods treat biomechanical waveforms as continuous functions. Functional Principal Component Analysis (fPCA)
fPCA(x, n_components = 5, smooth = FALSE, smooth_param = 10)fPCA(x, n_components = 5, smooth = FALSE, smooth_param = 10)
x |
A PhysioExperiment object or matrix (time x observations). |
n_components |
Number of principal components to retain. |
smooth |
Logical; if TRUE, smooths the data before analysis. |
smooth_param |
Smoothing parameter (higher = smoother). |
Performs functional PCA on waveform data to identify the main modes of variation in movement patterns.
fPCA decomposes waveform variability into orthogonal modes. In gait analysis, PC1 often represents overall amplitude, PC2 timing/phase shifts, and subsequent PCs capture more subtle shape variations.
A list of class "fpca_result" containing:
scores |
PC scores for each observation (observations x components) |
loadings |
PC loadings/eigenfunctions (time x components) |
variance_explained |
Proportion of variance explained by each PC |
cumulative_variance |
Cumulative variance explained |
mean_function |
Mean waveform across observations |
Ramsay JO, Silverman BW (2005). "Functional Data Analysis." 2nd ed. Springer.
reconstructFPCA() for waveform reconstruction from fPCA results,
plotFPCA() (in PhysioMoCap) for visualization of fPCA results,
registerCurves() for separating phase and amplitude variation.
# Simulate gait angle data (100 time points x 30 subjects) set.seed(123) t <- seq(0, 100, length.out = 100) base_curve <- sin(2 * pi * t / 100) * 30 # Add subject variability data <- sapply(1:30, function(i) { amplitude <- rnorm(1, 1, 0.2) phase <- rnorm(1, 0, 5) base_curve * amplitude + rnorm(100, 0, 2) }) pe <- PhysioExperiment(assays = list(values = data), samplingRate = 100) fpca_result <- fPCA(pe, n_components = 4)# Simulate gait angle data (100 time points x 30 subjects) set.seed(123) t <- seq(0, 100, length.out = 100) base_curve <- sin(2 * pi * t / 100) * 30 # Add subject variability data <- sapply(1:30, function(i) { amplitude <- rnorm(1, 1, 0.2) phase <- rnorm(1, 0, 5) base_curve * amplitude + rnorm(100, 0, 2) }) pe <- PhysioExperiment(assays = list(values = data), samplingRate = 100) fpca_result <- fPCA(pe, n_components = 4)
Returns indices of channels matching specified types.
getChannelsByType(x, types)getChannelsByType(x, types)
x |
A PhysioExperiment object. |
types |
Character vector of channel types to match. |
Integer vector of matching channel indices.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
setChannelTypes for assigning channel types,
pickChannels for subsetting by channel,
dropChannels for removing channels
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame( label = c("Fz", "EOG1", "EMG1", "Oz"), type = c("EEG", "EOG", "EMG", "EEG") ), samplingRate = 100 ) # Get EEG channels eeg_idx <- getChannelsByType(pe, "EEG") # c(1, 4)pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame( label = c("Fz", "EOG1", "EMG1", "Oz"), type = c("EEG", "EOG", "EMG", "EEG") ), samplingRate = 100 ) # Get EEG channels eeg_idx <- getChannelsByType(pe, "EEG") # c(1, 4)
Get electrode positions
getElectrodePositions(x)getElectrodePositions(x)
x |
A PhysioExperiment object. |
A data.frame with x, y, z columns or NULL if not set.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
setElectrodePositions for setting positions,
applyMontage for standard electrode layouts,
channelNames for channel labels
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(300), nrow = 100, ncol = 3)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz")), samplingRate = 100 ) pe <- applyMontage(pe, "10-20") getElectrodePositions(pe)pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(300), nrow = 100, ncol = 3)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz")), samplingRate = 100 ) pe <- applyMontage(pe, "10-20") getElectrodePositions(pe)
Get events from a PhysioExperiment object
getEvents(x, type = NULL)getEvents(x, type = NULL)
x |
A PhysioExperiment object. |
type |
Optional character vector of event types to filter. |
A PhysioEvents object or DataFrame of events.
Delorme A, Makeig S (2004). "EEGLAB: an open source toolbox for analysis of single-trial EEG dynamics." Journal of Neuroscience Methods, 134(1), 9-21.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
setEvents for attaching events,
addEvents for appending events,
removeEvents for removing events,
nEvents for event count
# Create PhysioExperiment with events pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 100)), samplingRate = 100 ) events <- PhysioEvents( onset = c(1, 2, 3), type = c("stimulus", "response", "stimulus") ) pe <- setEvents(pe, events) # Get all events getEvents(pe) # Get only stimulus events getEvents(pe, type = "stimulus")# Create PhysioExperiment with events pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 100)), samplingRate = 100 ) events <- PhysioEvents( onset = c(1, 2, 3), type = c("stimulus", "response", "stimulus") ) pe <- setEvents(pe, events) # Get all events getEvents(pe) # Get only stimulus events getEvents(pe, type = "stimulus")
Get reference electrode
getReference(x)getReference(x)
x |
A PhysioExperiment object. |
Character string of reference electrode or NULL.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
setReference for setting the reference,
channelInfo for full channel metadata
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) pe <- setReference(pe, "Cz") getReference(pe) # "Cz"pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) pe <- setReference(pe, "Cz") getReference(pe) # "Cz"
Provides various strategies for handling NA values in signal data.
handleNA( x, method = c("interpolate", "omit", "zero", "mean", "locf", "none"), ... )handleNA( x, method = c("interpolate", "omit", "zero", "mean", "locf", "none"), ... )
x |
Numeric vector or matrix. |
method |
Method for handling NA: "omit" (remove), "interpolate" (linear), "zero" (replace with 0), "mean" (replace with mean), "locf" (last observation carried forward), or "none" (no action). |
... |
Additional arguments passed to interpolation methods. |
Data with NA values handled according to the specified method.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
replaceNA for handling NA in PhysioExperiment assays,
fillEdgeNA for edge-specific NA filling,
checkNA for NA validation
x <- c(1, NA, 3, NA, 5) # Linear interpolation handleNA(x, method = "interpolate") # Replace with mean handleNA(x, method = "mean") # Last observation carried forward handleNA(x, method = "locf")x <- c(1, NA, 3, NA, 5) # Linear interpolation handleNA(x, method = "interpolate") # Replace with mean handleNA(x, method = "mean") # Last observation carried forward handleNA(x, method = "locf")
Convenience wrapper that runs harmonizeChannels,
harmonizeReference and harmonizeMontage in turn.
Pass ref = NULL or system = NULL to skip a step.
harmonize( long, target_labels = NULL, rename = NULL, ref = "average", system = "10-20" )harmonize( long, target_labels = NULL, rename = NULL, ref = "average", system = "10-20" )
long |
A |
target_labels, rename
|
As in |
ref |
Common reference label, or |
system |
Montage system, or |
A fully harmonized PhysioLongitudinal.
Intersects and reorders the channels of every session of a
PhysioLongitudinal so they share one common channel set in identical
order. Channels absent from any session are dropped; an optional
rename map first unifies differing label conventions.
harmonizeChannels(long, target_labels = NULL, rename = NULL)harmonizeChannels(long, target_labels = NULL, rename = NULL)
long |
A |
target_labels |
Optional character vector giving the desired channel set
and order. Restricted to channels common to all sessions. If |
rename |
Optional named character vector |
The PhysioLongitudinal with harmonized sessions; each session
records the kept/dropped/renamed channels and a provenance activity.
harmonize, harmonizeReport,
pickChannels
mk <- function(labs) PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(50 * length(labs)), 50, length(labs))), colData = S4Vectors::DataFrame(label = labs), samplingRate = 100) pl <- PhysioLongitudinal( baseline = mk(c("Fz", "Cz", "Pz", "Oz")), discharge = mk(c("Cz", "Fz", "Pz"))) h <- harmonizeChannels(pl) channelNames(session(h, "baseline"))mk <- function(labs) PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(50 * length(labs)), 50, length(labs))), colData = S4Vectors::DataFrame(label = labs), samplingRate = 100) pl <- PhysioLongitudinal( baseline = mk(c("Fz", "Cz", "Pz", "Oz")), discharge = mk(c("Cz", "Fz", "Pz"))) h <- harmonizeChannels(pl) channelNames(session(h, "baseline"))
Applies a consistent electrode montage to every session (building on
applyMontage).
harmonizeMontage(long, system = c("10-20", "10-10", "10-5"))harmonizeMontage(long, system = c("10-20", "10-10", "10-5"))
long |
A |
system |
Montage system: one of |
The PhysioLongitudinal with a common montage and a provenance
activity on each session.
Records a common reference on every session (building on
setReference), so that getReference is identical
across sessions.
harmonizeReference(long, ref)harmonizeReference(long, ref)
long |
A |
ref |
Character reference label (e.g. |
The PhysioLongitudinal with a common reference and a
provenance activity on each session.
Report the channels dropped / renamed per session by harmonization
harmonizeReport(long)harmonizeReport(long)
long |
A harmonized |
A named list (one entry per session) with kept, dropped
and renamed channels.
Regular streams put sample i at offset + (i - 1) / rate. A
stream that carries measured timestamps - because the acquisition reported
them, or because it has gaps or drift - is not on that grid, and operations
that can only work with a regular grid must say so rather than approximate.
hasMeasuredTimes(x, stream = NULL)hasMeasuredTimes(x, stream = NULL)
x |
A |
stream |
Stream name, or |
Logical, named when stream is NULL.
Quick check for NA presence in PhysioExperiment data.
hasNA(x, assay_name = NULL)hasNA(x, assay_name = NULL)
x |
A PhysioExperiment object. |
assay_name |
Optional specific assay to check. |
Logical indicating presence of NA values.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
checkNA for detailed NA statistics,
naSummary for per-assay NA summary,
replaceNA for handling NA values
pe <- PhysioExperiment( assays = list(raw = matrix(1:4, nrow = 2)), samplingRate = 100 ) hasNA(pe)pe <- PhysioExperiment( assays = list(raw = matrix(1:4, nrow = 2)), samplingRate = 100 ) hasNA(pe)
Computes the ICC using ANOVA-based methods following Shrout & Fleiss (1979). Supports one-way and two-way random/mixed models, agreement and consistency types, and single or average unit measures.
icc( ratings, model = c("twoway", "oneway"), type = c("agreement", "consistency"), unit = c("single", "average") )icc( ratings, model = c("twoway", "oneway"), type = c("agreement", "consistency"), unit = c("single", "average") )
ratings |
Numeric matrix with subjects as rows and raters/sessions as columns. |
model |
Character; ICC model type:
|
type |
Character; agreement type:
|
unit |
Character; unit of measurement:
|
The function implements the six ICC forms from Shrout & Fleiss (1979):
ICC(1,1): One-way random, single measures
ICC(1,k): One-way random, average measures
ICC(2,1): Two-way random, absolute agreement, single measures
ICC(2,k): Two-way random, absolute agreement, average measures
ICC(3,1): Two-way mixed, consistency, single measures
ICC(3,k): Two-way mixed, consistency, average measures
A list with components:
ICC value
Lower bound of 95 percent confidence interval
Upper bound of 95 percent confidence interval
F statistic from ANOVA
p-value for testing ICC = 0
Model used
Agreement type used
Shrout PE, Fleiss JL (1979). Intraclass correlations: Uses in assessing rater reliability. Psychological Bulletin, 86(2), 420-428.
sem() for standard error of measurement based on ICC,
mdc() for minimal detectable change,
blandAltman() for agreement analysis between methods.
# Test-retest reliability ratings <- matrix(c( 9, 2, 5, 8, 6, 1, 3, 2, 8, 4, 6, 8, 7, 1, 2, 6, 10, 5, 6, 9, 6, 2, 4, 7 ), nrow = 6, ncol = 4, byrow = TRUE) result <- icc(ratings, model = "twoway", type = "agreement") result$icc# Test-retest reliability ratings <- matrix(c( 9, 2, 5, 8, 6, 1, 3, 2, 8, 4, 6, 8, 7, 1, 2, 6, 10, 5, 6, 9, 6, 2, 4, 7 ), nrow = 6, ncol = 4, byrow = TRUE) result <- icc(ratings, model = "twoway", type = "agreement") result$icc
Test whether an object is a PhysioBiomarker
is.PhysioBiomarker(x)is.PhysioBiomarker(x)
x |
Any object. |
TRUE if x is a PhysioBiomarker, otherwise FALSE.
is.PhysioBiomarker(physioBiomarker(1, "x")) is.PhysioBiomarker(42)is.PhysioBiomarker(physioBiomarker(1, "x")) is.PhysioBiomarker(42)
Returns the number of time points (rows) in the default assay.
## S4 method for signature 'PhysioExperiment' length(x)## S4 method for signature 'PhysioExperiment' length(x)
x |
A PhysioExperiment object. |
Integer scalar giving the number of time points (rows) in the
default assay, or 0L if no assays are present.
Huber, W., et al. (2015). "Orchestrating high-throughput genomic analysis with Bioconductor." Nature Methods, 12(2), 115-121. doi:10.1038/nmeth.3252
Morgan, M., et al. (2022). "S4Vectors: Foundation of vector-like and list-like containers in Bioconductor." R package.
dim,PhysioExperiment-method for full dimensions,
nChannels for the number of channels,
duration for duration in seconds
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) length(pe) # 100pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) length(pe) # 100
Appends a timestamped, agent-attributed PROV activity. Call this from any
operation that returns a modified PhysioExperiment.
logStep( x, step, params = list(), package = NA_character_, version = NA_character_ )logStep( x, step, params = list(), package = NA_character_, version = NA_character_ )
x |
A |
step |
Character scalar naming the operation (e.g. |
params |
Named list of parameters to record. |
package, version
|
Optional originating package name and version. |
x with the step appended (the input is unchanged; a modified
copy is returned).
pe <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) pe <- logStep(pe, "filterSignals", params = list(low = 1, high = 40)) provenance(pe)pe <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) pe <- logStep(pe, "filterSignals", params = list(low = 1, high = 40)) provenance(pe)
Computes the minimal detectable change from the standard error of measurement.
mdc(sem_value, confidence = 0.95)mdc(sem_value, confidence = 0.95)
sem_value |
Numeric; the standard error of measurement. |
confidence |
Numeric; confidence level (default 0.95). |
MDC is computed as:
where .
At 95\
Numeric MDC value.
Shrout PE, Fleiss JL (1979). "Intraclass Correlations: Uses in Assessing Rater Reliability." Psychological Bulletin, 86(2), 420-428.
sem() for computing standard error of measurement,
icc() for computing intraclass correlation coefficients.
sem_val <- 2.5 mdc(sem_val, confidence = 0.95)sem_val <- 2.5 mdc(sem_val, confidence = 0.95)
Rebuilds a container saved when the multimodal class carried
experiments / alignment / sampleMap /
couplingResults into the unified MultiPhysioExperiment.
migrateContainer(object, verbose = TRUE) ## S4 method for signature 'MultiPhysioExperiment' updateObject(object, ..., verbose = FALSE)migrateContainer(object, verbose = TRUE) ## S4 method for signature 'MultiPhysioExperiment' updateObject(object, ..., verbose = FALSE)
object |
A legacy container (or any object; non-legacy input is returned unchanged). |
verbose |
Emit a message describing what was carried over. |
... |
Ignored. |
Two things are deliberately not converted:
The old model had no absolute origin, so clock$t0 is set to
NA rather than to a fabricated zero.
sampleMap and the cached couplingResults have no
counterpart in the unified model. They are carried into
clock$migrated_from with their origin rather than dropped, and the
cache is not reused: it was keyed without reference to the signals or
the clock, so nothing here can show it still matches its inputs.
The declared sampling rates in the old alignment table are checked against the real streams; a disagreement is reported rather than silently resolved.
# round-trips a current object unchanged m <- MultiPhysioExperiment(a = PhysioExperiment( assays = list(raw = matrix(0, 10, 2)), samplingRate = 10)) identical(migrateContainer(m), m)# round-trips a current object unchanged m <- MultiPhysioExperiment(a = PhysioExperiment( assays = list(raw = matrix(0, 10, 2)), samplingRate = 10)) identical(migrateContainer(m), m)
These are the names the container carried when it lived in
PhysioCrossModal. They are kept so existing code runs unchanged and
return the same types they always did: experiments() a plain named
list (not a SimpleList), modalities() a character
vector, samplingRates() a named numeric, nModalities() an
integer.
experiments(x) ## S4 method for signature 'MultiPhysioExperiment' experiments(x) experiments(x) <- value ## S4 replacement method for signature 'MultiPhysioExperiment' experiments(x) <- value modalities(x) ## S4 method for signature 'MultiPhysioExperiment' modalities(x) samplingRates(x) ## S4 method for signature 'MultiPhysioExperiment' samplingRates(x) nModalities(x) ## S4 method for signature 'MultiPhysioExperiment' nModalities(x) alignment(x) ## S4 method for signature 'MultiPhysioExperiment' alignment(x) alignment(x) <- value ## S4 replacement method for signature 'MultiPhysioExperiment' alignment(x) <- valueexperiments(x) ## S4 method for signature 'MultiPhysioExperiment' experiments(x) experiments(x) <- value ## S4 replacement method for signature 'MultiPhysioExperiment' experiments(x) <- value modalities(x) ## S4 method for signature 'MultiPhysioExperiment' modalities(x) samplingRates(x) ## S4 method for signature 'MultiPhysioExperiment' samplingRates(x) nModalities(x) ## S4 method for signature 'MultiPhysioExperiment' nModalities(x) alignment(x) ## S4 method for signature 'MultiPhysioExperiment' alignment(x) alignment(x) <- value ## S4 replacement method for signature 'MultiPhysioExperiment' alignment(x) <- value
x |
A |
value |
For |
alignment() is a view computed from the clock, not a stored
second copy. Assigning to it writes back into the clock, so the two can never
disagree.
As described above; setters return the modified object.
Holds several PhysioExperiment streams on one shared clock. Nothing is
resampled and no synchronisation is estimated.
MultiRatePhysioExperiment() is the former name, kept as a
compatibility entry point. It builds the same container and returns the
legacy subclass so that existing is() tests keep passing.
MultiPhysioExperiment( streams = list(), ..., t0 = 0, offsets = NULL, reference_rate = NULL, clock = NULL, experiments = NULL, alignment = NULL ) MultiRatePhysioExperiment( streams = list(), ..., t0 = 0, offsets = NULL, reference_rate = NULL, clock = NULL, experiments = NULL, alignment = NULL )MultiPhysioExperiment( streams = list(), ..., t0 = 0, offsets = NULL, reference_rate = NULL, clock = NULL, experiments = NULL, alignment = NULL ) MultiRatePhysioExperiment( streams = list(), ..., t0 = 0, offsets = NULL, reference_rate = NULL, clock = NULL, experiments = NULL, alignment = NULL )
streams |
A named list of |
... |
Additional named |
t0 |
Origin of the shared clock in seconds (default 0). Use |
offsets |
Named numeric of per-stream start offsets in seconds relative
to |
reference_rate |
Default grid rate in Hz for
|
clock |
Optional pre-built clock list, used instead of |
experiments |
Legacy alias for |
alignment |
Legacy alignment |
Omitting offsets declares that the streams started together; that
assumption is recorded in the clock (offsets_assumed) rather than being
indistinguishable from a measured alignment. A partially specified
offsets is an error rather than being completed with zeros.
A MultiPhysioExperiment.
streamRates, timeWindow,
resampleToCommon
kin <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(100 * 3), 100, 3)), samplingRate = 100) emg <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(2000 * 2), 2000, 2)), samplingRate = 2000) mpe <- MultiPhysioExperiment(kinematics = kin, emg = emg) streamRates(mpe) # a measured alignment: EMG started 137 ms after the clock origin MultiPhysioExperiment(streams = list(kinematics = kin, emg = emg), offsets = c(kinematics = 0, emg = 0.137))kin <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(100 * 3), 100, 3)), samplingRate = 100) emg <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(2000 * 2), 2000, 2)), samplingRate = 2000) mpe <- MultiPhysioExperiment(kinematics = kin, emg = emg) streamRates(mpe) # a measured alignment: EMG started 137 ms after the clock origin MultiPhysioExperiment(streams = list(kinematics = kin, emg = emg), offsets = c(kinematics = 0, emg = 0.137))
MultiPhysioExperiment holds several PhysioExperiment streams
recorded together - the classic motion-capture situation of, say, 100 Hz
kinematics alongside 1000 Hz force-plate analog and 2000 Hz EMG, or the NWB
TimeSeries / LSL-XDF / C3D POINT+ANALOG pattern. Streams that happen
to share a sampling rate use the same class; nothing about it is specific to
mixed rates.
Each stream keeps its own sampling rate and length. The container adds one
thing: a shared clock that says how the streams line up in time. There
is deliberately no second alignment table - the clock is the single source of
truth, and alignment is a view derived from it.
Construction never resamples and never estimates synchronisation. Holding the
time correspondence and converting the signals onto a common grid
(resampleToCommon) are separate steps.
streamsA SimpleList of named PhysioExperiment objects.
clockA list describing the shared clock (see above).
t0Origin of the shared clock, in seconds. NA means the
recording has no known absolute origin; that absence is preserved rather
than replaced by a fabricated zero.
offsetsNamed numeric, one entry per stream, giving where each
stream starts in seconds relative to t0. Negative values are
allowed (a stream that started before the origin).
reference_rateDefault grid rate used when the signals are explicitly converted to a common rate. It never overrides a stream's own sampling rate.
offsets_assumedTRUE when the offsets were not supplied
and simultaneous start was assumed. A known common clock and an assumed
one are different claims, so they are recorded differently.
schemaInteger schema version, for migration.
Extra elements are preserved untouched, which is where measured timestamps, gap records or drift corrections belong.
Sample i of a stream sits at offset + (i - 1) / samplingRate
seconds relative to t0. streamTimeIndex returns
exactly that and does not add t0.
MultiPhysioExperiment for the constructor,
timeWindow, resampleToCommon,
alignStreams
Display, size and stream-extraction methods for MultiPhysioExperiment
## S4 method for signature 'MultiPhysioExperiment' length(x) ## S4 method for signature 'MultiPhysioExperiment' names(x) ## S4 method for signature 'MultiPhysioExperiment,ANY,ANY' x[[i, j, ...]] ## S4 method for signature 'MultiPhysioExperiment' dim(x) ## S4 method for signature 'MultiPhysioExperiment' show(object)## S4 method for signature 'MultiPhysioExperiment' length(x) ## S4 method for signature 'MultiPhysioExperiment' names(x) ## S4 method for signature 'MultiPhysioExperiment,ANY,ANY' x[[i, j, ...]] ## S4 method for signature 'MultiPhysioExperiment' dim(x) ## S4 method for signature 'MultiPhysioExperiment' show(object)
i |
Stream name or index (for |
j, ...
|
Ignored. |
object, x
|
A |
length() the number of streams; dim() a matrix of
per-stream c(nsamples, nchannels); [[ the selected
PhysioExperiment stream; show() is called for its side effect.
MultiRatePhysioExperiment is the former name of what is now
MultiPhysioExperiment-class. It survives as an empty subclass so
that objects saved under the old name keep loading, validating and
dispatching, and so that code testing is(x, "MultiRatePhysioExperiment")
keeps working. It adds no slots and no second clock model.
New code should use MultiPhysioExperiment.
Convenience wrapper around .fitMVAR that optionally selects the
model order automatically via mvarOrderSelect.
mvarFit( X, order = NULL, method = c("ols", "yulewalker", "nuttall-strand"), max_order = 20L, criterion = c("bic", "aic") )mvarFit( X, order = NULL, method = c("ols", "yulewalker", "nuttall-strand"), max_order = 20L, criterion = c("bic", "aic") )
X |
A numeric matrix ( |
order |
Integer order, or |
method |
Estimator (see |
max_order |
Maximum order for automatic selection (default: 20). |
criterion |
Selection criterion when |
An object of class "mvar": a list with A, Sigma,
order, method, and n_channels.
set.seed(1) X <- matrix(rnorm(600), ncol = 3) fit <- mvarFit(X, order = 2) dim(fit$A)set.seed(1) X <- matrix(rnorm(600), ncol = 3) fit <- mvarFit(X, order = 2) dim(fit$A)
Fits MVAR models over a range of orders and returns the order minimising the
Akaike (AIC) or Bayesian (BIC) information criterion. For an m-channel model
of order p with n effective samples the criteria are
n log det(Sigma_p) + 2 m^2 p (AIC) and
n log det(Sigma_p) + log(n) m^2 p (BIC).
mvarOrderSelect( X, max_order = 20L, criterion = c("bic", "aic"), method = c("ols", "yulewalker", "nuttall-strand") )mvarOrderSelect( X, max_order = 20L, criterion = c("bic", "aic"), method = c("ols", "yulewalker", "nuttall-strand") )
X |
A numeric matrix ( |
max_order |
Maximum order to consider (default: 20). |
criterion |
|
method |
Estimator passed to |
A list with the selected order, the chosen criterion,
and a data.frame criteria of order, aic,
bic.
Convenience wrapper around .mvarSpectral for a fitted
"mvar" model.
mvarTransfer(fit, freqs, sr)mvarTransfer(fit, freqs, sr)
fit |
An |
freqs |
Numeric vector of frequencies in Hz. |
sr |
Sampling rate in Hz. |
A list as returned by .mvarSpectral (H, S,
A, frequencies).
set.seed(1) X <- matrix(rnorm(600), ncol = 3) fit <- mvarFit(X, order = 2) sp <- mvarTransfer(fit, freqs = seq(1, 40, by = 1), sr = 100) dim(sp$H)set.seed(1) X <- matrix(rnorm(600), ncol = 3) fit <- mvarFit(X, order = 2) sp <- mvarTransfer(fit, freqs = seq(1, 40, by = 1), sr = 100) dim(sp$H)
Returns a summary of NA values across all assays.
naSummary(x)naSummary(x)
x |
A PhysioExperiment object. |
A data.frame with NA statistics for each assay.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
hasNA for quick NA check,
checkNA for detailed NA validation,
replaceNA for handling NA values
pe <- PhysioExperiment( assays = list( raw = matrix(c(1, NA, 3, 4), nrow = 2), filtered = matrix(1:4, nrow = 2) ), samplingRate = 100 ) naSummary(pe)pe <- PhysioExperiment( assays = list( raw = matrix(c(1, NA, 3, 4), nrow = 2), filtered = matrix(1:4, nrow = 2) ), samplingRate = 100 ) naSummary(pe)
Get number of channels
nChannels(x)nChannels(x)
x |
A PhysioExperiment object. |
Integer number of channels.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
channelNames for channel labels,
channelInfo for full channel metadata,
pickChannels for subsetting channels
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) nChannels(pe) # 4pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) nChannels(pe) # 4
Get number of events
nEvents(x)nEvents(x)
x |
A PhysioEvents object. |
Integer count of events.
Delorme A, Makeig S (2004). "EEGLAB: an open source toolbox for analysis of single-trial EEG dynamics." Journal of Neuroscience Methods, 134(1), 9-21.
getEvents for retrieving events,
PhysioEvents for the event constructor,
addEvents for appending events
events <- PhysioEvents(onset = c(1, 2, 3), type = "stimulus") nEvents(events)events <- PhysioEvents(onset = c(1, 2, 3), type = "stimulus") nEvents(events)
Compares an observed marker to seeded published normative reference values
(read from inst/extdata/normative/*.csv), returning a z-score and
percentile. This is a scaffold seeded with a few quantitative-EEG markers
(delta-alpha ratio, brain symmetry index); extend the CSVs to add markers.
When the marker, age band, or montage is unknown the z-score and percentile
are returned as NA without raising an error.
normativeLookup(marker, age = NULL, montage = NULL)normativeLookup(marker, age = NULL, montage = NULL)
marker |
A PhysioBiomarker (its name and value are used), or a
character marker name (then only reference values are returned, with the
z-score/percentile |
age |
Optional numeric age in years used to select an age-stratified reference row. |
montage |
Optional character montage used to select a montage-specific reference row. |
A named list: marker, value, mean, sd,
unit, source, z_score, percentile, and
matched (logical). Unknown lookups return NA fields with
matched = FALSE.
physioBiomarker(), NormativeReference(), zScore()
bm <- physioBiomarker(2.35, "DAR") normativeLookup(bm, age = 40) normativeLookup("UNKNOWN_MARKER") # returns NA fields, no errorbm <- physioBiomarker(2.35, "DAR") normativeLookup(bm, age = 40) normativeLookup("UNKNOWN_MARKER") # returns NA fields, no error
Construct a NormativeReference
NormativeReference( metric, strata, source = NA_character_, version = NA_character_, unit = NA_character_ )NormativeReference( metric, strata, source = NA_character_, version = NA_character_, unit = NA_character_ )
metric |
Character metric name. |
strata |
|
source |
Character citation (default |
version |
Character version tag (default |
unit |
Character unit (default |
A NormativeReference object.
ref <- NormativeReference( "gait_speed", strata = data.frame( sex = c("M", "F"), mean = c(1.34, 1.24), sd = c(0.20, 0.19), n = c(50, 50) ), source = "Bohannon 2011", unit = "m/s" ) zScore(ref, 1.10, by = list(sex = "M"))ref <- NormativeReference( "gait_speed", strata = data.frame( sex = c("M", "F"), mean = c(1.34, 1.24), sd = c(0.20, 0.19), n = c(50, 50) ), source = "Bohannon 2011", unit = "m/s" ) zScore(ref, 1.10, by = list(sex = "M"))
Holds published reference (normative) values for a single metric, stratified by one or more grouping variables (e.g. age band, sex). Downstream code turns an observed value into a z-score or a percent-of-predicted against the matching stratum, which is the basis for most rehabilitation cut-offs (6MWT, gait speed, grip strength, spirometry, ...).
## S4 method for signature 'NormativeReference' show(object)## S4 method for signature 'NormativeReference' show(object)
object |
A |
The show method returns NULL invisibly and is called for
the side effect of printing a compact summary.
metricCharacter name of the metric (e.g. "gait_speed").
stratadata.frame with one row per stratum. Must contain numeric
mean and sd columns; may contain n; any remaining
columns are the stratification keys used for matching.
sourceCharacter citation for the reference values.
versionCharacter version tag for the reference set.
unitCharacter measurement unit.
Normative comparisons for an observed value
zScore(ref, value, by = NULL) ## S4 method for signature 'NormativeReference' zScore(ref, value, by = NULL) percentPredicted(ref, value, by = NULL) ## S4 method for signature 'NormativeReference' percentPredicted(ref, value, by = NULL)zScore(ref, value, by = NULL) ## S4 method for signature 'NormativeReference' zScore(ref, value, by = NULL) percentPredicted(ref, value, by = NULL) ## S4 method for signature 'NormativeReference' percentPredicted(ref, value, by = NULL)
ref |
A |
value |
Numeric observed value(s). |
by |
Named list or vector selecting the stratum (e.g.
|
zScore() the standard score ;
percentPredicted() .
ref <- NormativeReference( "gait_speed", strata = data.frame( sex = c("M", "F"), mean = c(1.34, 1.24), sd = c(0.20, 0.19) ), source = "Bohannon 2011", unit = "m/s" ) zScore(ref, 1.10, by = list(sex = "M")) percentPredicted(ref, 1.10, by = list(sex = "M"))ref <- NormativeReference( "gait_speed", strata = data.frame( sex = c("M", "F"), mean = c(1.34, 1.24), sd = c(0.20, 0.19) ), source = "Bohannon 2011", unit = "m/s" ) zScore(ref, 1.10, by = list(sex = "M")) percentPredicted(ref, 1.10, by = list(sex = "M"))
Number of streams
nStreams(x)nStreams(x)
x |
A |
Integer count of streams.
Builds a PhysioBiomarker carrying not just the value but the metadata a
clinical reader needs: a confidence interval, a published reference range,
reliability indices (ICC / SEM / MDC, per COSMIN reporting), and the
measurement provenance (assay, band, method, software version). The value
prints with its CI and, when a reference range is supplied, its normative
percentile; BiocGenerics::as.data.frame() flattens every field for tabular reporting.
physioBiomarker( value, name, unit = NA_character_, ci = NULL, reference_range = NULL, reliability = list(), provenance = list(), interpretation = NA_character_ )physioBiomarker( value, name, unit = NA_character_, ci = NULL, reference_range = NULL, reliability = list(), provenance = list(), interpretation = NA_character_ )
value |
Numeric scalar value. |
name |
Character biomarker name (e.g. |
unit |
Character measurement unit (default |
ci |
Numeric length-2 confidence interval, or |
reference_range |
Numeric length-2 published reference (normal) range,
or |
reliability |
Named list of reliability indices, typically |
provenance |
Named list describing how the value was computed, typically
|
interpretation |
Optional character interpretation label. |
A PhysioBiomarker object.
PhysioBiomarker(), normativeLookup(), is.PhysioBiomarker(),
icc(), sem(), mdc()
bm <- physioBiomarker( value = 2.35, name = "DAR", unit = "ratio", ci = c(1.90, 2.80), reference_range = c(0.5, 1.2), reliability = list(icc = 0.82, sem = 0.15, mdc = 0.42), provenance = list(assay = "psd", band = "delta/alpha", method = "welch", software_version = "1.0.0") ) bm as.data.frame(bm)bm <- physioBiomarker( value = 2.35, name = "DAR", unit = "ratio", ci = c(1.90, 2.80), reference_range = c(0.5, 1.2), reliability = list(icc = 0.82, sem = 0.15, mdc = 0.42), provenance = list(assay = "psd", band = "delta/alpha", method = "welch", software_version = "1.0.0") ) bm as.data.frame(bm)
Construct a PhysioBiomarker
PhysioBiomarker( name, value, unit = NA_character_, ci = numeric(0), interpretation = NA_character_, parameters = list() )PhysioBiomarker( name, value, unit = NA_character_, ci = numeric(0), interpretation = NA_character_, parameters = list() )
name |
Character biomarker name. |
value |
Numeric scalar value. |
unit |
Character unit (default |
ci |
Numeric length-2 confidence interval (default none). |
interpretation |
Optional character interpretation. |
parameters |
Named list of parameters used. |
A PhysioBiomarker object.
PhysioBiomarker("SDNN", 42, unit = "ms", ci = c(38, 46))PhysioBiomarker("SDNN", 42, unit = "ms", ci = c(38, 46))
Extends AnalysisResult with a scalar value, unit, optional
confidence interval, and interpretation - the unit reporting consumes.
## S4 method for signature 'PhysioBiomarker' show(object)## S4 method for signature 'PhysioBiomarker' show(object)
object |
An object to display. |
The show method for PhysioBiomarker returns NULL
invisibly and is called for the side effect of printing a compact summary.
nameCharacter biomarker name.
valueNumeric scalar value.
unitCharacter measurement unit.
ciNumeric length-2 confidence interval, or length-0 if none.
interpretationOptional character interpretation label.
reference_rangeNumeric length-2 published reference (normal) range, or length-0 if none.
reliabilityNamed list of reliability indices, typically icc,
sem, and mdc (see icc, sem,
mdc).
provenance_infoNamed list describing how the value was computed,
typically assay, band, method, and
software_version.
Construct a PhysioCohort
PhysioCohort( subjects = list(), ..., colData = NULL, group = NULL, metadata = list() )PhysioCohort( subjects = list(), ..., colData = NULL, group = NULL, metadata = list() )
subjects |
A named list of subjects - each a
|
... |
Additional named subjects. |
colData |
Optional |
group |
Optional vector (length = number of subjects) giving each
subject's group / trial arm; stored as |
metadata |
Optional cohort-level metadata |
A PhysioCohort.
cohortDesign, subjects,
addSubject
mk <- function() PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(200), 100, 2)), samplingRate = 250) coh <- PhysioCohort( "sub-01" = PhysioLongitudinal(baseline = mk(), discharge = mk(), design = S4Vectors::DataFrame(session_id = c("baseline", "discharge"), visit_label = c("baseline", "discharge"), days_from_baseline = c(0, 42))), "sub-02" = mk(), group = c("treatment", "control")) coh cohortDesign(coh)mk <- function() PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(200), 100, 2)), samplingRate = 250) coh <- PhysioCohort( "sub-01" = PhysioLongitudinal(baseline = mk(), discharge = mk(), design = S4Vectors::DataFrame(session_id = c("baseline", "discharge"), visit_label = c("baseline", "discharge"), days_from_baseline = c(0, 42))), "sub-02" = mk(), group = c("treatment", "control")) coh cohortDesign(coh)
PhysioCohort is the multi-subject layer above
PhysioLongitudinal: it holds many participants, each represented
by their own longitudinal timeline of sessions, alongside a subject-level
colData table (id, group/arm, diagnosis, age, sex, side, ...). This is
the container a rehabilitation study needs - a cohort or the arms of a trial,
as subjects x sessions - and the shape downstream pipelines, trial analyses
and prognostic models iterate over (see cohortDesign).
A bare PhysioExperiment / MultiRatePhysioExperiment
passed as a subject is auto-wrapped into a single-session
PhysioLongitudinal (visit label "session"), so cross-sectional
and longitudinal cohorts share one API.
subjectsA SimpleList of named PhysioLongitudinal subjects.
colDataA DataFrame with one row per subject; a subject_id
column aligns to (and is ordered as) names(subjects).
metadataA list of cohort-level metadata.
PhysioCohort (constructor), cohortDesign,
subjects, PhysioLongitudinal
Size, subsetting and display for PhysioCohort
## S4 method for signature 'PhysioCohort' length(x) ## S4 method for signature 'PhysioCohort,ANY,ANY,ANY' x[i, j, ..., drop = TRUE] ## S4 method for signature 'PhysioCohort' show(object)## S4 method for signature 'PhysioCohort' length(x) ## S4 method for signature 'PhysioCohort,ANY,ANY,ANY' x[i, j, ..., drop = TRUE] ## S4 method for signature 'PhysioCohort' show(object)
x |
A |
i |
Subject index / name / logical (for |
j, drop
|
Ignored (present for |
... |
Ignored. |
object |
A |
length() the number of subjects; [ a subset
PhysioCohort; show() is called for its side effect.
Create a PhysioEvents object
PhysioEvents( onset = numeric(0), duration = numeric(0), type = character(0), value = character(0) )PhysioEvents( onset = numeric(0), duration = numeric(0), type = character(0), value = character(0) )
onset |
Numeric vector of event onset times in seconds. |
duration |
Numeric vector of event durations in seconds. |
type |
Character vector of event types (e.g., "stimulus", "response"). |
value |
Character vector of event values/labels. |
A PhysioEvents object.
Delorme A, Makeig S (2004). "EEGLAB: an open source toolbox for analysis of single-trial EEG dynamics." Journal of Neuroscience Methods, 134(1), 9-21.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
setEvents for attaching events to a PhysioExperiment,
getEvents for retrieving events,
nEvents for event count
# Create events for a simple experiment events <- PhysioEvents( onset = c(1.0, 2.5, 4.0, 5.5), duration = c(0.5, 0.5, 0.5, 0.5), type = c("stimulus", "response", "stimulus", "response"), value = c("target", "hit", "distractor", "false_alarm") ) events # Create events with single type stim_events <- PhysioEvents( onset = c(1, 2, 3, 4, 5), type = "stimulus" )# Create events for a simple experiment events <- PhysioEvents( onset = c(1.0, 2.5, 4.0, 5.5), duration = c(0.5, 0.5, 0.5, 0.5), type = c("stimulus", "response", "stimulus", "response"), value = c("target", "hit", "distractor", "false_alarm") ) events # Create events with single type stim_events <- PhysioEvents( onset = c(1, 2, 3, 4, 5), type = "stimulus" )
Functions for managing experimental events (triggers, markers, annotations) within PhysioExperiment objects. PhysioEvents class
A simple S4 class to store event information as a DataFrame.
eventsA DataFrame containing event information with columns: onset (numeric), duration (numeric), type (character), value (character).
Creates a new PhysioExperiment instance, which extends
SummarizedExperiment with a samplingRate slot for
physiological signal data.
PhysioExperiment( assays = S4Vectors::SimpleList(), rowData = NULL, colData = NULL, metadata = list(), samplingRate = as.numeric(NA), provenance = NULL )PhysioExperiment( assays = S4Vectors::SimpleList(), rowData = NULL, colData = NULL, metadata = list(), samplingRate = as.numeric(NA), provenance = NULL )
assays |
A |
rowData |
Feature-level metadata as a |
colData |
Sample-level metadata as a |
metadata |
Optional experiment-level metadata list. |
samplingRate |
Numeric scalar sampling rate in Hz. |
provenance |
Optional. Either a character source identifier (e.g. a file
path or dataset id) - in which case an initial PROV |
A PhysioExperiment object containing the supplied assays,
row/column metadata, and sampling rate.
Huber, W., et al. (2015). "Orchestrating high-throughput genomic analysis with Bioconductor." Nature Methods, 12(2), 115-121. doi:10.1038/nmeth.3252
Morgan, M., et al. (2022). "S4Vectors: Foundation of vector-like and list-like containers in Bioconductor." R package.
samplingRate for accessing the sampling rate,
defaultAssay for retrieving the first assay name,
channelInfo for channel metadata,
setEvents for attaching event information
# Create a simple PhysioExperiment with random EEG-like data # 1000 time points, 4 channels eeg_data <- matrix(rnorm(1000 * 4), nrow = 1000, ncol = 4) colnames(eeg_data) <- c("Fz", "Cz", "Pz", "Oz") pe <- PhysioExperiment( assays = list(raw = eeg_data), colData = S4Vectors::DataFrame( label = c("Fz", "Cz", "Pz", "Oz"), type = rep("EEG", 4) ), samplingRate = 250 ) pe # Access sampling rate samplingRate(pe) # Create with multiple assays pe2 <- PhysioExperiment( assays = list(raw = eeg_data, filtered = eeg_data * 0.5), samplingRate = 500 )# Create a simple PhysioExperiment with random EEG-like data # 1000 time points, 4 channels eeg_data <- matrix(rnorm(1000 * 4), nrow = 1000, ncol = 4) colnames(eeg_data) <- c("Fz", "Cz", "Pz", "Oz") pe <- PhysioExperiment( assays = list(raw = eeg_data), colData = S4Vectors::DataFrame( label = c("Fz", "Cz", "Pz", "Oz"), type = rep("EEG", 4) ), samplingRate = 250 ) pe # Access sampling rate samplingRate(pe) # Create with multiple assays pe2 <- PhysioExperiment( assays = list(raw = eeg_data, filtered = eeg_data * 0.5), samplingRate = 500 )
The PhysioExperiment class extends SummarizedExperiment to store
multi-modal physiological signal data alongside metadata such as sampling
rate. This file defines the class, its validity checks, and the
user-facing constructor.
samplingRateNumeric scalar describing the acquisition frequency in Hz.
Huber, W., et al. (2015). "Orchestrating high-throughput genomic analysis with Bioconductor." Nature Methods, 12(2), 115-121. doi:10.1038/nmeth.3252
Morgan, M., et al. (2022). "S4Vectors: Foundation of vector-like and list-like containers in Bioconductor." R package.
PhysioExperiment for the constructor,
samplingRate for accessing the sampling rate,
channelInfo for channel metadata
Construct a PhysioLongitudinal container
PhysioLongitudinal(sessions = list(), ..., design = NULL, subject = NULL)PhysioLongitudinal(sessions = list(), ..., design = NULL, subject = NULL)
sessions |
A named list of |
... |
Additional named sessions. |
design |
Optional |
subject |
Optional one-row |
A PhysioLongitudinal with sessions in chronological order.
mk <- function(sr = 250) PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(100 * 2), 100, 2)), samplingRate = sr) pl <- PhysioLongitudinal( baseline = mk(), discharge = mk(), design = S4Vectors::DataFrame( session_id = c("baseline", "discharge"), visit_label = c("baseline", "discharge"), days_from_baseline = c(0, 42)), subject = S4Vectors::DataFrame(id = "sub-01", dx = "stroke", side = "L")) design(pl)mk <- function(sr = 250) PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(100 * 2), 100, 2)), samplingRate = sr) pl <- PhysioLongitudinal( baseline = mk(), discharge = mk(), design = S4Vectors::DataFrame( session_id = c("baseline", "discharge"), visit_label = c("baseline", "discharge"), days_from_baseline = c(0, 42)), subject = S4Vectors::DataFrame(id = "sub-01", dx = "stroke", side = "L")) design(pl)
PhysioLongitudinal is a subject-level container that links several
recording sessions of the same participant across a rehabilitation timeline -
typically baseline, mid, discharge and followup
visits. Each session is a PhysioExperiment (or
MultiRatePhysioExperiment); a design-schema DataFrame
records the visit label, days from baseline and condition of each session, and
a one-row subject DataFrame carries participant-level metadata (id,
diagnosis, affected side). Sessions are always kept in chronological order
(ascending days_from_baseline). It mirrors the
MultiAssayExperiment pattern, BIDS ses- entities and the OMOP
visit-occurrence model.
sessionsA SimpleList of named PhysioExperiment /
MultiRatePhysioExperiment sessions.
designA DataFrame with one row per session
(session_id, visit_label, days_from_baseline,
condition).
subjectA one-row DataFrame of subject metadata (id,
dx, side).
Ramos, M., et al. (2017). Software for the integration of multiomics experiments in Bioconductor. Cancer Research, 77(21).
PhysioLongitudinal for the constructor,
addSession, session
Display, size and subsetting for PhysioLongitudinal
## S4 method for signature 'PhysioLongitudinal' length(x) ## S4 method for signature 'PhysioLongitudinal,ANY,ANY,ANY' x[i, j, ..., drop = TRUE] ## S4 method for signature 'PhysioLongitudinal' show(object)## S4 method for signature 'PhysioLongitudinal' length(x) ## S4 method for signature 'PhysioLongitudinal,ANY,ANY,ANY' x[i, j, ..., drop = TRUE] ## S4 method for signature 'PhysioLongitudinal' show(object)
x |
A |
i |
Session index/name/logical (for |
j, drop
|
Ignored (present for |
... |
Ignored. |
object |
A |
length() the number of sessions; [ a subset
PhysioLongitudinal; show() is called for its side effect.
Returns n colors from a colour-vision-deficiency-safe palette. The
"qualitative" palette is the Okabe & Ito set (distinguishable under
deuteranopia / protanopia); "sequential" is viridis; and
"diverging" is a CVD-safe blue-red diverging ramp. Shared across all
ecosystem visualizations so figures are consistent and accessible.
physioPalette(n = 8L, type = c("qualitative", "sequential", "diverging"))physioPalette(n = 8L, type = c("qualitative", "sequential", "diverging"))
n |
Number of colors to return. |
type |
Palette family: |
Character vector of n hex colors. The qualitative palette has
only 8 colour-vision-safe entries; requesting n > 8 qualitative
colours emits a warning and returns a best-effort interpolation that is no
longer reliably distinguishable under colour-vision deficiency (no
qualitative palette is). Prefer faceting or a sequential encoding for more
than 8 categories.
Okabe, M. & Ito, K. (2008). Color Universal Design. Garnier et al. (viridis). Zeileis et al. (2020). colorspace, JSS 96(1).
physioPalette(4) physioPalette(7, "sequential") physioPalette(5, "diverging")physioPalette(4) physioPalette(7, "sequential") physioPalette(5, "diverging")
Creates a new PhysioExperiment with only selected channels.
pickChannels(x, channels)pickChannels(x, channels)
x |
A PhysioExperiment object. |
channels |
Integer indices or character names of channels to keep. |
A new PhysioExperiment with selected channels.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
dropChannels for removing channels,
getChannelsByType for finding channels by type,
channelNames for available channel labels
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) # Pick by index pe_subset <- pickChannels(pe, c(1, 3)) nChannels(pe_subset) # 2 # Pick by name pe_frontal <- pickChannels(pe, c("Fz", "Cz"))pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) # Pick by index pe_subset <- pickChannels(pe, c(1, 3)) nChannels(pe_subset) # 2 # Pick by name pe_frontal <- pickChannels(pe, c("Fz", "Cz"))
Print fPCA result
## S3 method for class 'fpca_result' print(x, ...)## S3 method for class 'fpca_result' print(x, ...)
x |
An fpca_result object |
... |
Additional arguments (unused) |
Ramsay JO, Silverman BW (2005). "Functional Data Analysis." 2nd ed. Springer.
fPCA() for performing functional principal component analysis,
plotFPCA() (in PhysioMoCap) for visualization of fPCA results,
reconstructFPCA() for waveform reconstruction from fPCA scores.
Every analysis operation that returns a modified PhysioExperiment
should record an append-only, timestamped, agent-attributed provenance entry
following the W3C PROV data model (Lebo et al. 2013). Each entry captures a
PROV activity (the operation), the entity it generated, the
inputs it used, the responsible agent, its start/end times, and
the parameters (also serialized as JSON for downstream export).
provenance(x) ## S4 method for signature 'PhysioExperiment' provenance(x) provenance(x) <- value ## S4 replacement method for signature 'PhysioExperiment' provenance(x) <- value ## S4 method for signature 'MultiPhysioExperiment' provenance(x) ## S4 method for signature 'PhysioLongitudinal' provenance(x) ## S4 method for signature 'PhysioCohort' provenance(x)provenance(x) ## S4 method for signature 'PhysioExperiment' provenance(x) provenance(x) <- value ## S4 replacement method for signature 'PhysioExperiment' provenance(x) <- value ## S4 method for signature 'MultiPhysioExperiment' provenance(x) ## S4 method for signature 'PhysioLongitudinal' provenance(x) ## S4 method for signature 'PhysioCohort' provenance(x)
x |
A |
value |
A provenance entry list (used by the setter). |
The log is stored in the object's metadata() under the key
"provenance". Storing it in metadata (rather than a dedicated S4 slot)
is deliberate: objects serialized before provenance existed, or by any other
SummarizedExperiment tool, deserialize cleanly and simply report an
empty log, with no need for a class-version updateObject migration.
provenance() returns a data.frame with one row per
recorded PROV activity. Columns include the PROV-O fields activity,
entity, used, generated, agent,
startedAtTime, endedAtTime, params_json, plus the
back-compatible step, timestamp, user, package,
version, and params. Empty if none recorded.
Lebo, T., Sahoo, S., & McGuinness, D. (2013). PROV-O: The PROV Ontology. W3C Recommendation.
logStep, withProvenance,
recordActivity
pe <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) pe <- logStep(pe, "filterSignals", params = list(low = 1, high = 40)) provenance(pe)pe <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) pe <- logStep(pe, "filterSignals", params = list(low = 1, high = 40)) provenance(pe)
Returns a stable hash of the semantic content of the provenance log - the ordered sequence of processing steps and their parameters - deliberately excluding wall-clock timestamps and the machine-specific agent/user. The same pipeline (same steps, same parameters) therefore always hashes to the same value, while any change to a step or its parameters changes the hash. Useful as a reproducibility fingerprint for a processed object.
provenanceHash(x, algo = "xxhash64")provenanceHash(x, algo = "xxhash64")
x |
A |
algo |
Hash algorithm passed to |
A single character hash string.
pe <- PhysioExperiment(assays = list(raw = matrix(rnorm(40), 10, 4)), samplingRate = 100) pe <- logStep(pe, "filterSignals", params = list(low = 1, high = 40)) provenanceHash(pe)pe <- PhysioExperiment(assays = list(raw = matrix(rnorm(40), 10, 4)), samplingRate = 100) pe <- logStep(pe, "filterSignals", params = list(low = 1, high = 40)) provenanceHash(pe)
Tests the null hypothesis that the angles are uniformly distributed on the circle (no preferred direction) against a unimodal concentration. A small p-value means the angles cluster around a mean direction – e.g. that a coupling angle is consistently in-phase rather than random.
rayleighTest(angles, units = c("degrees", "radians"))rayleighTest(angles, units = c("degrees", "radians"))
angles |
Numeric vector of angles. |
units |
|
an htest: Rayleigh Z = n * rbar^2, p.value (Zar 1999
approximation), and the estimated mean direction.
Zar JH (1999) eq. 27.2-27.4; Fisher NI (1993).
circularSummary(), watsonWilliamsTest()
set.seed(1) rayleighTest(rnorm(40, mean = 30, sd = 12))$p.value # clustered -> smallset.seed(1) rayleighTest(rnorm(40, mean = 30, sd = 12))$p.value # clustered -> small
Concatenates two PhysioExperiment objects along the time (row) axis.
Both objects must have the same number of channels and matching sampling
rates. Event onsets in y are offset by the duration of x.
rbindPhysio(x, y)rbindPhysio(x, y)
x |
A PhysioExperiment object. |
y |
A PhysioExperiment object to concatenate. |
A PhysioExperiment object with time points from both
x and y concatenated, combined rowData, and merged events.
Huber, W., et al. (2015). "Orchestrating high-throughput genomic analysis with Bioconductor." Nature Methods, 12(2), 115-121. doi:10.1038/nmeth.3252
Morgan, M., et al. (2022). "S4Vectors: Foundation of vector-like and list-like containers in Bioconductor." R package.
cbindPhysio for combining along the channel axis,
extractWindow for extracting a time window,
[ forgeneral subsetting
pe1 <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) pe2 <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) # Concatenate in time pe_concat <- rbindPhysio(pe1, pe2) length(pe_concat) # 200pe1 <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) pe2 <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) # Concatenate in time pe_concat <- rbindPhysio(pe1, pe2) length(pe_concat) # 200
readRDS() performs no validity check, so a container saved before the
multimodal classes were unified comes back structurally invalid and says
nothing about it; the failure only surfaces when a slot is first touched.
This reader detects that layout and converts it, reporting what it did.
readPhysioRDS(file, migrate = TRUE, verbose = TRUE)readPhysioRDS(file, migrate = TRUE, verbose = TRUE)
file |
Path to an |
migrate |
Convert a legacy container (default). When |
verbose |
Describe the migration. |
The file is only read - it is never rewritten. Save the returned object somewhere new if the converted form should persist.
The stored object, migrated when applicable.
Reconstructs individual waveforms using a subset of principal components.
reconstructFPCA(fpca_result, n_components = NULL, observation = NULL)reconstructFPCA(fpca_result, n_components = NULL, observation = NULL)
fpca_result |
An fpca_result object from fPCA(). |
n_components |
Number of components to use for reconstruction. |
observation |
Indices of observations to reconstruct. If NULL, all. |
Matrix of reconstructed waveforms (time x observations).
Ramsay JO, Silverman BW (2005). "Functional Data Analysis." 2nd ed. Springer.
fPCA() for performing the decomposition,
plotFPCA() (in PhysioMoCap) for visualizing fPCA results.
# Create sample data and run fPCA first set.seed(123) t <- seq(0, 100, length.out = 100) base_curve <- sin(2 * pi * t / 100) * 30 data <- sapply(1:20, function(i) base_curve * rnorm(1, 1, 0.2) + rnorm(100, 0, 2)) fpca_result <- fPCA(data, n_components = 4) # Reconstruct using only first 2 PCs reconstructed <- reconstructFPCA(fpca_result, n_components = 2)# Create sample data and run fPCA first set.seed(123) t <- seq(0, 100, length.out = 100) base_curve <- sin(2 * pi * t / 100) * 30 data <- sapply(1:20, function(i) base_curve * rnorm(1, 1, 0.2) + rnorm(100, 0, 2)) fpca_result <- fPCA(data, n_components = 4) # Reconstruct using only first 2 PCs reconstructed <- reconstructFPCA(fpca_result, n_components = 2)
Evaluates expr (an operation that transforms x and returns a
PhysioExperiment), timing it to fill the PROV startedAtTime /
endedAtTime, and appends one activity to the result. The input's
provenance log is carried onto the result if the operation dropped it.
recordActivity( x, activity, expr, params = list(), input_assay = NA_character_, output_assay = NA_character_, agent = NA_character_, software_version = NA_character_, package = NA_character_ )recordActivity( x, activity, expr, params = list(), input_assay = NA_character_, output_assay = NA_character_, agent = NA_character_, software_version = NA_character_, package = NA_character_ )
x |
The input |
activity |
Character scalar naming the PROV activity. |
expr |
An expression, evaluated lazily, that returns the modified object
(e.g. |
params |
Named list of parameters to record. |
input_assay, output_assay, agent, software_version, package
|
As in
|
The object returned by expr, with the timed activity appended.
pe <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) scale2 <- function(p) { SummarizedExperiment::assay(p, "raw") <- SummarizedExperiment::assay(p, "raw") * 2; p } pe <- recordActivity(pe, "rescale", scale2(pe), params = list(gain = 2)) provenance(pe)$activitype <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) scale2 <- function(p) { SummarizedExperiment::assay(p, "raw") <- SummarizedExperiment::assay(p, "raw") * 2; p } pe <- recordActivity(pe, "rescale", scale2(pe), params = list(gain = 2)) provenance(pe)$activity
One trial can be captured by several devices, so this table allows more than
one row per trial and is unique on
(subject_id, session_id, trial_id, recording_id).
recordingMap(x) recordingMap(x) <- valuerecordingMap(x) recordingMap(x) <- value
x |
A |
value |
A data frame with the four key columns,
|
time_correspondence states what is known about placing the recordings
relative to one another:
"measured"The relative times were measured - a shared trigger,
say. reference names what they are measured against (a common clock
or a reference recording_id) and offset gives the value in
seconds. Elapsed time between trials may be computed.
"order_only"Only the order is known. Elapsed time may not be computed - row order is not a duration.
"unknown"Nothing relates the recordings.
A row may declare "measured" while leaving reference or
offset missing: the table records what was declared, and
elapsedBetweenTrials refuses to compute from it. The state name
alone never authorises a duration.
The recording map, or the modified container.
The recordings held by a trial set
recordings(x)recordings(x)
x |
A |
The named list of MultiPhysioExperiment recordings.
Aligns waveforms by estimating and removing phase variation. Uses landmark registration or continuous registration.
registerCurves( x, method = c("continuous", "landmark"), landmarks = NULL, template = NULL )registerCurves( x, method = c("continuous", "landmark"), landmarks = NULL, template = NULL )
x |
A PhysioExperiment object or matrix (time x observations). |
method |
Registration method: "landmark" or "continuous". |
landmarks |
For landmark method, matrix of landmark times (landmarks x obs). |
template |
Template curve to align to. If NULL, uses mean. |
Phase variation (timing differences) can obscure amplitude differences in biomechanical data. Registration separates phase and amplitude variation.
A list containing:
registered |
Registered waveforms |
warping |
Warping functions |
template |
Template used for registration |
Ramsay JO, Silverman BW (2005). "Functional Data Analysis." 2nd ed. Springer.
fPCA() for functional PCA after registration,
plotGaitCycle() (in PhysioMoCap) for plotting registered gait waveforms.
# Simulate data with phase variation set.seed(123) t <- seq(0, 100, length.out = 100) data <- sapply(1:20, function(i) { phase_shift <- rnorm(1, 0, 10) t_shifted <- t + phase_shift sin(2 * pi * t_shifted / 100) * 30 + rnorm(100, 0, 2) }) pe <- PhysioExperiment(assays = list(values = data), samplingRate = 100) reg_result <- registerCurves(pe, method = "continuous")# Simulate data with phase variation set.seed(123) t <- seq(0, 100, length.out = 100) data <- sapply(1:20, function(i) { phase_shift <- rnorm(1, 0, 10) t_shifted <- t + phase_shift sin(2 * pi * t_shifted / 100) * 30 + rnorm(100, 0, 2) }) pe <- PhysioExperiment(assays = list(values = data), samplingRate = 100) reg_result <- registerCurves(pe, method = "continuous")
Register and dispatch named operations
registerOperation(name, fn, modality = NULL, overwrite = FALSE) getOperation(name) availableOperations(modality = NULL) unregisterOperation(name)registerOperation(name, fn, modality = NULL, overwrite = FALSE) getOperation(name) availableOperations(modality = NULL) unregisterOperation(name)
name |
Case-insensitive operation key. |
fn |
The operation function. |
modality |
For |
overwrite |
If |
registerOperation() invisibly returns fn; getOperation()
returns the registered function; availableOperations() returns a
data.frame of name/modality (the name column holds normalized,
lower-cased keys); unregisterOperation() invisibly returns TRUE if an
operation was removed.
Other plugin-api:
physio-registry,
registerReader(),
registerWriter()
registerOperation("demo_detrend", function(x) x - mean(x), modality = "generic", overwrite = TRUE) availableOperations() availableOperations(modality = "generic") op <- getOperation("demo_detrend") unregisterOperation("demo_detrend")registerOperation("demo_detrend", function(x) x - mean(x), modality = "generic", overwrite = TRUE) availableOperations() availableOperations(modality = "generic") op <- getOperation("demo_detrend") unregisterOperation("demo_detrend")
Register and dispatch file readers
registerReader(format, fn, ext = NULL, overwrite = FALSE) getReader(format) availableReaders() unregisterReader(format)registerReader(format, fn, ext = NULL, overwrite = FALSE) getReader(format) availableReaders() unregisterReader(format)
format |
Case-insensitive format key (e.g. |
fn |
The reader function; its first argument should be a file path. |
ext |
Optional character vector of file extensions handled (no dot). |
overwrite |
If |
registerReader() invisibly returns fn; getReader() returns the
registered function; availableReaders() returns a data.frame of
format/ext (the format column holds normalized, lower-cased keys, and
the frame has zero rows when nothing is registered); unregisterReader()
invisibly returns TRUE if a reader was removed.
Other plugin-api:
physio-registry,
registerOperation(),
registerWriter()
registerReader("demo_csv", function(file, ...) read.csv(file, ...), ext = "csv", overwrite = TRUE) availableReaders() r <- getReader("DEMO_CSV") # case-insensitive unregisterReader("demo_csv")registerReader("demo_csv", function(file, ...) read.csv(file, ...), ext = "csv", overwrite = TRUE) availableReaders() r <- getReader("DEMO_CSV") # case-insensitive unregisterReader("demo_csv")
Register and dispatch file writers
registerWriter(format, fn, ext = NULL, overwrite = FALSE) getWriter(format) availableWriters() unregisterWriter(format)registerWriter(format, fn, ext = NULL, overwrite = FALSE) getWriter(format) availableWriters() unregisterWriter(format)
format |
Case-insensitive format key (e.g. |
fn |
The writer function; its first arguments should be the object to write and a file path. |
ext |
Optional character vector of file extensions handled (no dot). |
overwrite |
If |
registerWriter() invisibly returns fn; getWriter() returns the
registered function; availableWriters() returns a data.frame of
format/ext (the format column holds normalized, lower-cased keys, and
the frame has zero rows when nothing is registered); unregisterWriter()
invisibly returns TRUE if a writer was removed.
Other plugin-api:
physio-registry,
registerOperation(),
registerReader()
registerWriter("demo_csv", function(x, file, ...) write.csv(x, file, ...), ext = "csv", overwrite = TRUE) availableWriters() unregisterWriter("demo_csv")registerWriter("demo_csv", function(x, file, ...) write.csv(x, file, ...), ext = "csv", overwrite = TRUE) availableWriters() unregisterWriter("demo_csv")
Remove events from a PhysioExperiment object
removeEvents(x, type = NULL, indices = NULL)removeEvents(x, type = NULL, indices = NULL)
x |
A PhysioExperiment object. |
type |
Optional event types to remove. If NULL, removes all events. |
indices |
Optional integer indices of events to remove. |
The modified PhysioExperiment object.
Delorme A, Makeig S (2004). "EEGLAB: an open source toolbox for analysis of single-trial EEG dynamics." Journal of Neuroscience Methods, 134(1), 9-21.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
getEvents for retrieving events,
addEvents for appending events,
setEvents for replacing all events
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 100)), samplingRate = 100 ) pe <- addEvents(pe, onset = c(1, 2, 3), type = c("stimulus", "response", "stimulus")) pe <- removeEvents(pe, type = "response") nEvents(pe)pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 100)), samplingRate = 100 ) pe <- addEvents(pe, onset = c(1, 2, 3), type = c("stimulus", "response", "stimulus")) pe <- removeEvents(pe, type = "response") nEvents(pe)
Rename channels
renameChannels(x, old_names, new_names)renameChannels(x, old_names, new_names)
x |
A PhysioExperiment object. |
old_names |
Character vector of current names. |
new_names |
Character vector of new names. |
Modified PhysioExperiment object.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
channelNames for reading channel labels,
channelInfo for full channel metadata,
pickChannels for subsetting channels
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) # Rename channels pe <- renameChannels(pe, c("Fz", "Cz"), c("F3", "C3")) channelNames(pe)pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) # Rename channels pe <- renameChannels(pe, c("Fz", "Cz"), c("F3", "C3")) channelNames(pe)
Creates a new assay with NA values handled according to the specified method.
replaceNA( x, method = "interpolate", input_assay = NULL, output_assay = "na_handled" )replaceNA( x, method = "interpolate", input_assay = NULL, output_assay = "na_handled" )
x |
A PhysioExperiment object. |
method |
Method for handling NA (see handleNA). |
input_assay |
Input assay name. If NULL, uses default assay. |
output_assay |
Output assay name. Default is "na_handled". |
Modified PhysioExperiment with new assay.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
handleNA for the underlying NA handling strategies,
checkNA for NA validation,
hasNA for quick NA presence check
pe <- PhysioExperiment( assays = list(raw = matrix(c(1, NA, 3, NA, 5, 6), nrow = 3)), samplingRate = 100 ) # Interpolate NA values pe <- replaceNA(pe, method = "interpolate")pe <- PhysioExperiment( assays = list(raw = matrix(c(1, NA, 3, NA, 5, 6), nrow = 3)), samplingRate = 100 ) # Interpolate NA values pe <- replaceNA(pe, method = "interpolate")
Interpolates every stream onto a shared time grid at rate, honouring
each stream's start offset on the shared clock, and returns a single
PhysioExperiment whose channels are the union of all streams'
channels (prefixed with the stream name). Grid positions before/after a
stream's coverage are NA.
resampleToCommon(x, rate = NULL)resampleToCommon(x, rate = NULL)
x |
A |
rate |
Target sampling rate in Hz (default: the clock reference rate). |
A single-rate PhysioExperiment with an "aligned" assay.
kin <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(100 * 2), 100, 2)), samplingRate = 100) emg <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(1000 * 2), 1000, 2)), samplingRate = 1000) mpe <- MultiPhysioExperiment(kin = kin, emg = emg) aligned <- resampleToCommon(mpe, 1000) dim(SummarizedExperiment::assay(aligned, "aligned"))kin <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(100 * 2), 100, 2)), samplingRate = 100) emg <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(1000 * 2), 1000, 2)), samplingRate = 1000) mpe <- MultiPhysioExperiment(kin = kin, emg = emg) aligned <- resampleToCommon(mpe, 1000) dim(SummarizedExperiment::assay(aligned, "aligned"))
Resolve an EventQuery to get filtered events
resolveQuery(q)resolveQuery(q)
q |
An EventQuery object |
Data frame of filtered events
pe <- PhysioExperiment(assays = list(raw = matrix(rnorm(400), 100, 4)), samplingRate = 100) pe <- addEvents(pe, onset = c(1, 2, 3), type = "stimulus") resolveQuery(eventQuery(pe))pe <- PhysioExperiment(assays = list(raw = matrix(rnorm(400), 100, 4)), samplingRate = 100) pe <- addEvents(pe, onset = c(1, 2, 3), type = "stimulus") resolveQuery(eventQuery(pe))
Convert sample indices to times
samplesToTime(x, samples)samplesToTime(x, samples)
x |
A PhysioExperiment object. |
samples |
Integer vector of sample indices. |
Numeric vector of times in seconds.
Delorme A, Makeig S (2004). "EEGLAB: an open source toolbox for analysis of single-trial EEG dynamics." Journal of Neuroscience Methods, 134(1), 9-21.
timeToSamples for the inverse conversion,
samplingRate for the sampling rate,
timeIndex for the full time vector
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 100)), samplingRate = 100 ) samplesToTime(pe, c(1L, 51L, 101L))pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 100)), samplingRate = 100 ) samplesToTime(pe, c(1L, 51L, 101L))
These helper functions expose common slots and derived quantities for
PhysioExperiment objects.
Get or set sampling rate
samplingRate(x) ## S4 method for signature 'PhysioExperiment' samplingRate(x) samplingRate(x) <- value ## S4 replacement method for signature 'PhysioExperiment' samplingRate(x) <- valuesamplingRate(x) ## S4 method for signature 'PhysioExperiment' samplingRate(x) samplingRate(x) <- value ## S4 replacement method for signature 'PhysioExperiment' samplingRate(x) <- value
x |
A PhysioExperiment object. |
value |
Numeric scalar for the new sampling rate in Hz. |
For samplingRate(x): a numeric scalar giving the sampling
rate in Hz. For samplingRate(x) <- value: the modified
PhysioExperiment object (returned invisibly).
Huber, W., et al. (2015). "Orchestrating high-throughput genomic analysis with Bioconductor." Nature Methods, 12(2), 115-121. doi:10.1038/nmeth.3252
Morgan, M., et al. (2022). "S4Vectors: Foundation of vector-like and list-like containers in Bioconductor." R package.
PhysioExperiment for the constructor,
defaultAssay for the default assay name,
duration for signal duration,
timeIndex for time point vector
# Create example data pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(100), nrow = 10)), samplingRate = 250 ) # Get sampling rate samplingRate(pe) # Set sampling rate samplingRate(pe) <- 500 samplingRate(pe)# Create example data pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(100), nrow = 10)), samplingRate = 250 ) # Get sampling rate samplingRate(pe) # Set sampling rate samplingRate(pe) <- 500 samplingRate(pe)
Colorblind-safe discrete colour / fill scales for ggplot2
scale_color_physio(...) scale_colour_physio(...) scale_fill_physio(...)scale_color_physio(...) scale_colour_physio(...) scale_fill_physio(...)
... |
Passed to |
A ggplot2 discrete scale using physioPalette.
if (requireNamespace("ggplot2", quietly = TRUE)) { p <- ggplot2::ggplot( iris, ggplot2::aes(Sepal.Length, Sepal.Width, color = Species)) + ggplot2::geom_point() + scale_color_physio() + theme_physio() }if (requireNamespace("ggplot2", quietly = TRUE)) { p <- ggplot2::ggplot( iris, ggplot2::aes(Sepal.Length, Sepal.Width, color = Species)) + ggplot2::geom_point() + scale_color_physio() + theme_physio() }
Computes the standard error of measurement from the SD of scores and a reliability coefficient (ICC or test-retest correlation).
sem(x, icc_value = NULL, reliability = NULL)sem(x, icc_value = NULL, reliability = NULL)
x |
Numeric vector of observed scores. Used to compute SD. |
icc_value |
Numeric; ICC value to use as the reliability coefficient. |
reliability |
Numeric; alternative reliability coefficient (e.g.,
test-retest correlation). Exactly one of |
SEM is computed as:
where is the reliability coefficient (ICC or correlation).
Numeric SEM value.
Shrout PE, Fleiss JL (1979). "Intraclass Correlations: Uses in Assessing Rater Reliability." Psychological Bulletin, 86(2), 420-428.
icc() for computing intraclass correlation coefficients,
mdc() for minimal detectable change based on SEM.
scores <- c(10, 12, 15, 11, 13, 14, 9, 16, 12, 11) sem(scores, icc_value = 0.90)scores <- c(10, 12, 15, 11, 13, 14, 9, 16, 12, 11) sem(scores, icc_value = 0.90)
Retrieve a single session by visit label or id
session(x, label)session(x, label)
x |
A |
label |
A |
The matching session, or an error if none/ambiguous.
Access the sessions of a PhysioLongitudinal
sessions(x) ## S4 method for signature 'PhysioLongitudinal' sessions(x) sessions(x) <- value ## S4 replacement method for signature 'PhysioLongitudinal' sessions(x) <- valuesessions(x) ## S4 method for signature 'PhysioLongitudinal' sessions(x) sessions(x) <- value ## S4 replacement method for signature 'PhysioLongitudinal' sessions(x) <- value
x |
A |
value |
A named list / SimpleList of sessions (setter). |
sessions() a SimpleList; setter returns the object.
Records a per-assay sampling rate in the object's metadata; useful after an assay has been resampled to a rate different from the main one.
setAssaySamplingRate(x, assay_name, rate)setAssaySamplingRate(x, assay_name, rate)
x |
A |
assay_name |
Name of the assay. |
rate |
Sampling rate for the assay in Hz. |
The PhysioExperiment with updated per-assay rate metadata.
assaySamplingRates,
MultiRatePhysioExperiment
pe <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2), decimated = matrix(rnorm(20), 10, 2)), samplingRate = 100) pe <- setAssaySamplingRate(pe, "decimated", 50) assaySamplingRates(pe)pe <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2), decimated = matrix(rnorm(20), 10, 2)), samplingRate = 100) pe <- setAssaySamplingRate(pe, "decimated", 50) assaySamplingRates(pe)
Assigns types (EEG, EMG, EOG, etc.) to channels.
setChannelTypes(x, types)setChannelTypes(x, types)
x |
A PhysioExperiment object. |
types |
Named character vector or list mapping channel names/indices to types. If unnamed, applies types in order. |
Modified PhysioExperiment object.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
getChannelsByType for querying channels by type,
channelInfo for full channel metadata,
setChannelUnits for assigning physical units
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "EOG1", "EMG1", "Oz")), samplingRate = 100 ) # Set all channels to same type pe <- setChannelTypes(pe, "EEG") # Set specific channel types by name pe <- setChannelTypes(pe, c(EOG1 = "EOG", EMG1 = "EMG"))pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "EOG1", "EMG1", "Oz")), samplingRate = 100 ) # Set all channels to same type pe <- setChannelTypes(pe, "EEG") # Set specific channel types by name pe <- setChannelTypes(pe, c(EOG1 = "EOG", EMG1 = "EMG"))
Assigns physical units to channels.
setChannelUnits(x, units)setChannelUnits(x, units)
x |
A PhysioExperiment object. |
units |
Character vector or named list of units. |
Modified PhysioExperiment object.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
setChannelTypes for assigning channel types,
channelInfo for full channel metadata
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) # Set all channels to same unit pe <- setChannelUnits(pe, "uV")pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) # Set all channels to same unit pe <- setChannelUnits(pe, "uV")
Assigns 3D electrode positions to channels.
setElectrodePositions(x, positions)setElectrodePositions(x, positions)
x |
A PhysioExperiment object. |
positions |
A data.frame or matrix with columns x, y, z and rows matching channels. Row names should match channel names. |
Modified PhysioExperiment object.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
getElectrodePositions for reading positions,
applyMontage for standard electrode layouts,
channelInfo for full channel metadata
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(300), nrow = 100, ncol = 3)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz")), samplingRate = 100 ) # Set electrode positions positions <- data.frame( x = c(0, 0, 0), y = c(0.71, 0, -0.71), z = c(0.71, 1, 0.71) ) pe <- setElectrodePositions(pe, positions)pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(300), nrow = 100, ncol = 3)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz")), samplingRate = 100 ) # Set electrode positions positions <- data.frame( x = c(0, 0, 0), y = c(0.71, 0, -0.71), z = c(0.71, 1, 0.71) ) pe <- setElectrodePositions(pe, positions)
Set events for a PhysioExperiment object
setEvents(x, events)setEvents(x, events)
x |
A PhysioExperiment object. |
events |
A PhysioEvents object or a data.frame with columns: onset, duration, type, value. |
The modified PhysioExperiment object.
Delorme A, Makeig S (2004). "EEGLAB: an open source toolbox for analysis of single-trial EEG dynamics." Journal of Neuroscience Methods, 134(1), 9-21.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
getEvents for retrieving events,
addEvents for appending events,
PhysioEvents for the event constructor
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 100)), samplingRate = 100 ) # Set events using PhysioEvents object events <- PhysioEvents(onset = c(1, 2, 3), type = "stimulus") pe <- setEvents(pe, events) # Set events using data.frame pe <- setEvents(pe, data.frame(onset = c(1, 2), type = "response"))pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 100)), samplingRate = 100 ) # Set events using PhysioEvents object events <- PhysioEvents(onset = c(1, 2, 3), type = "stimulus") pe <- setEvents(pe, events) # Set events using data.frame pe <- setEvents(pe, data.frame(onset = c(1, 2), type = "response"))
Records the reference electrode used for the recording.
setReference(x, reference)setReference(x, reference)
x |
A PhysioExperiment object. |
reference |
Character string naming the reference electrode. |
Modified PhysioExperiment object.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
getReference for reading the reference,
channelInfo for full channel metadata,
applyMontage for applying standard montages
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) # Set reference electrode pe <- setReference(pe, "average") getReference(pe) # "average"pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), samplingRate = 100 ) # Set reference electrode pe <- setReference(pe, "average") getReference(pe) # "average"
Show method for PhysioEvents
## S4 method for signature 'PhysioEvents' show(object)## S4 method for signature 'PhysioEvents' show(object)
object |
A PhysioEvents object. |
Returns NULL invisibly; called for the side effect of printing
a compact summary of the events to the console.
PhysioEvents for the constructor,
nEvents for event count
Standard S4 methods for PhysioExperiment objects including show, subsetting, and combining. Show method for PhysioExperiment
## S4 method for signature 'PhysioExperiment' show(object)## S4 method for signature 'PhysioExperiment' show(object)
object |
A PhysioExperiment object. |
Displays a summary of the PhysioExperiment object.
Invisibly returns NULL. Called for its side effect of
printing a human-readable summary to the console.
Huber, W., et al. (2015). "Orchestrating high-throughput genomic analysis with Bioconductor." Nature Methods, 12(2), 115-121. doi:10.1038/nmeth.3252
Morgan, M., et al. (2022). "S4Vectors: Foundation of vector-like and list-like containers in Bioconductor." R package.
PhysioExperiment for the constructor,
summary,PhysioExperiment-method for channel-level statistics,
as.data.frame,PhysioExperiment-method for conversion to data.frame
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) pe # Displays summarype <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) pe # Displays summary
Reports how much of [start, end] a stream actually covers. The
distinction the return value keeps is between what was observed and what
was derived: n_present is a count of real samples, while
n_expected and coverage depend on an assumed sampling scheme and
are NA when that scheme cannot decide them.
streamCoverage(x, stream, start, end, rule = "nominal", gap_factor = 1.5)streamCoverage(x, stream, start, end, rule = "nominal", gap_factor = 1.5)
x |
A |
stream |
Stream name. |
start, end
|
Bounds in seconds on the shared clock (closed interval, the
same meaning and tolerance as |
rule |
Name of the rule for |
gap_factor |
Multiple of the nominal period above which a step counts as a gap. |
Gaps are reported as intervals, not as a shortfall in a count, so a caller can
see where the recording stops. A step between measured sample times larger
than gap_factor times the nominal period counts as a gap; that factor
is an adopted criterion shared with PhysioCrossModal's interpolation
guard, and it separates acquisition jitter from a dropped sample rather than
proving that no gap exists.
For a stream with no measured times the sample times are reconstructed from
the start offset and the rate, so no gap can be found. That is a consequence
of the reconstruction, not a measurement, and rule$basis says so.
n_expected counts the points of a reference grid that fall inside the
interval. It is not (end - start) * rate, which measures a span rather
than a grid and overstates the count whenever the bounds do not land on sample
times – a whole, evenly sampled stream would then read as incomplete for being
asked about off its own sample times. The grid has step 1/rate and is
anchored on the stream's first sample time; for a measured stream that anchor
is an assumption, and rule$anchor, rule$step and
rule$basis report which grid was used.
A list with n_present, n_expected, coverage,
gaps (a data frame of start/end) and rule
(its name, gap_factor, the grid anchor and
step, and the basis the expected count rests on).
pe <- PhysioExperiment(assays = list(raw = matrix(1:5, ncol = 1)), samplingRate = 10, rowData = S4Vectors::DataFrame( time_from_t0 = c(0, 0.1, 0.2, 1.2, 1.3))) streamCoverage(MultiPhysioExperiment(a = pe), "a", 0, 1.3)pe <- PhysioExperiment(assays = list(raw = matrix(1:5, ncol = 1)), samplingRate = 10, rowData = S4Vectors::DataFrame( time_from_t0 = c(0, 0.1, 0.2, 1.2, 1.3))) streamCoverage(MultiPhysioExperiment(a = pe), "a", 0, 1.3)
Names of the streams
streamNames(x)streamNames(x)
x |
A |
Character vector of stream names.
Per-stream sampling rates
streamRates(x)streamRates(x)
x |
A |
Named numeric of sampling rates (Hz), one per stream.
Access the streams of a MultiPhysioExperiment
streams(x) ## S4 method for signature 'MultiPhysioExperiment' streams(x) streams(x) <- value ## S4 replacement method for signature 'MultiPhysioExperiment' streams(x) <- valuestreams(x) ## S4 method for signature 'MultiPhysioExperiment' streams(x) streams(x) <- value ## S4 replacement method for signature 'MultiPhysioExperiment' streams(x) <- value
x |
A |
value |
A named list / SimpleList of |
streams() a SimpleList; setter returns the updated object.
Returns offset + (i - 1) / samplingRate for each sample, i.e. seconds
relative to clock$t0. It deliberately does not add t0;
use commonClock(x)$t0 when an absolute time is needed.
streamTimeIndex(x, stream = NULL)streamTimeIndex(x, stream = NULL)
x |
A |
stream |
Stream name (or |
Numeric time vector (seconds from t0) for the stream, or a
named list of such vectors when stream is NULL.
Retrieve a single subject's longitudinal record by id
subject(x, id)subject(x, id)
x |
A |
id |
A subject id (name). |
The subject's PhysioLongitudinal.
Subject-level metadata
subjectData(x) ## S4 method for signature 'PhysioLongitudinal' subjectData(x) subjectData(x) <- value ## S4 replacement method for signature 'PhysioLongitudinal' subjectData(x) <- valuesubjectData(x) ## S4 method for signature 'PhysioLongitudinal' subjectData(x) subjectData(x) <- value ## S4 replacement method for signature 'PhysioLongitudinal' subjectData(x) <- value
x |
A |
value |
A one-row subject |
subjectData() the subject DataFrame.
Subject ids, subject count and group labels of a PhysioCohort
subjectIds(x) nSubjects(x) groups(x)subjectIds(x) nSubjects(x) groups(x)
x |
A |
subjectIds() a character vector; nSubjects() an integer;
groups() the colData$group vector (or NULL).
Subjects of a PhysioCohort
subjects(x) ## S4 method for signature 'PhysioCohort' subjects(x) subjects(x) <- value ## S4 replacement method for signature 'PhysioCohort' subjects(x) <- valuesubjects(x) ## S4 method for signature 'PhysioCohort' subjects(x) subjects(x) <- value ## S4 replacement method for signature 'PhysioCohort' subjects(x) <- value
x |
A |
value |
A named list / SimpleList of |
subjects() a SimpleList of PhysioLongitudinal.
Lists the trial tables of all sessions in a PhysioLongitudinal,
carrying the session each row came from. Without that column the rows would be
ambiguous: the same trial_id legitimately recurs in different sessions.
subjectTrials(x)subjectTrials(x)
x |
A |
A hierarchy with no trials returns an empty table with the same columns, not an error – "this subject has no trials recorded" is an answer.
A data frame of trials with a session column.
Subset a PhysioCohort by group (or a predicate on colData)
subsetCohort(x, group = NULL, subset = NULL)subsetCohort(x, group = NULL, subset = NULL)
x |
A |
group |
Optional character vector of group label(s) to keep. |
subset |
Optional logical vector (length = number of subjects) or an
expression evaluated in |
A PhysioCohort with the selected subjects.
Computes per-channel summary statistics (min, max, mean, sd, median) for the default assay. For 3D arrays, values are first averaged across the third dimension.
## S4 method for signature 'PhysioExperiment' summary(object, ...)## S4 method for signature 'PhysioExperiment' summary(object, ...)
object |
A PhysioExperiment object. |
... |
Additional arguments (not used). |
A data.frame with columns channel, min,
max, mean, sd, and median, with one row
per channel. Returns an empty data.frame if no assays are present.
R Core Team (2024). "R: A Language and Environment for Statistical Computing." R Foundation for Statistical Computing, Vienna, Austria.
PhysioExperiment for the constructor,
as.data.frame,PhysioExperiment-method for full data export,
channelNames for channel labels
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) summary(pe)pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(400), nrow = 100, ncol = 4)), colData = S4Vectors::DataFrame(label = c("Fz", "Cz", "Pz", "Oz")), samplingRate = 100 ) summary(pe)
A clean, accessible ggplot2 theme for x-biosignal figures
theme_physio(base_size = 11, base_family = "")theme_physio(base_size = 11, base_family = "")
base_size, base_family
|
Passed to the underlying base theme. |
A ggplot2 theme object.
if (requireNamespace("ggplot2", quietly = TRUE)) { p <- ggplot2::ggplot(mtcars, ggplot2::aes(wt, mpg)) + ggplot2::geom_point() + theme_physio() }if (requireNamespace("ggplot2", quietly = TRUE)) { p <- ggplot2::ggplot(mtcars, ggplot2::aes(wt, mpg)) + ggplot2::geom_point() + theme_physio() }
Computes a time vector for the default assay using the object's sampling rate.
timeIndex(x)timeIndex(x)
x |
A |
Numeric vector of time points in seconds.
Oostenveld R, Fries P, Maris E, Schoffelen JM (2011). "FieldTrip: Open source software for advanced analysis of MEG, EEG, and invasive electrophysiological data." Computational Intelligence and Neuroscience, 2011, 156869.
samplingRate for the sampling rate,
duration for signal duration,
timeToSamples for converting times to sample indices
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(40), nrow = 10, ncol = 4)), samplingRate = 100 ) head(timeIndex(pe))pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(40), nrow = 10, ncol = 4)), samplingRate = 100 ) head(timeIndex(pe))
Convert event times to sample indices
timeToSamples(x, times)timeToSamples(x, times)
x |
A PhysioExperiment object. |
times |
Numeric vector of times in seconds. |
Integer vector of sample indices.
Delorme A, Makeig S (2004). "EEGLAB: an open source toolbox for analysis of single-trial EEG dynamics." Journal of Neuroscience Methods, 134(1), 9-21.
samplesToTime for the inverse conversion,
samplingRate for the sampling rate,
timeIndex for the full time vector
pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 100)), samplingRate = 100 ) timeToSamples(pe, c(0, 0.5, 1))pe <- PhysioExperiment( assays = list(raw = matrix(rnorm(1000), nrow = 100)), samplingRate = 100 ) timeToSamples(pe, c(0, 0.5, 1))
Selects, from every stream, the samples whose time on the shared clock falls
in the closed interval [start, end], expressed in seconds relative to
clock$t0. Selection uses each sample's actual time, so a stream's
offset is honoured rather than ignored.
timeWindow( x, start, end, streams = NULL, drop_empty = FALSE, complete_only = FALSE )timeWindow( x, start, end, streams = NULL, drop_empty = FALSE, complete_only = FALSE )
x |
A |
start, end
|
Window bounds in seconds relative to |
streams |
Optional character vector of stream names to keep. |
drop_empty |
Exclude non-overlapping streams instead of failing. |
complete_only |
Keep only trials lying wholly inside the window. By default a trial overlapping the window is kept, truncated to it and marked, because the trial happened; the excluded ones are recorded either way. |
t0 is preserved and each stream's offset is updated to the time of its
first retained sample, so the result sits on the same clock as the input.
The input object is not modified.
A stream that does not overlap the window is an error by default, naming the
streams concerned: silently returning a container with fewer streams than
asked for has been a source of wrong answers. Pass drop_empty = TRUE
to exclude them deliberately; the exclusion and its reason are then recorded
in the result's provenance.
A MultiPhysioExperiment carrying the selected samples.
streamTimeIndex, resampleToCommon
a <- PhysioExperiment(S4Vectors::SimpleList(raw = matrix(rnorm(200), 100, 2)), samplingRate = 100) b <- PhysioExperiment(S4Vectors::SimpleList(raw = matrix(rnorm(500), 250, 2)), samplingRate = 250) mpe <- MultiPhysioExperiment(streams = list(a = a, b = b), offsets = c(a = 0, b = 0.2)) w <- timeWindow(mpe, 0.3, 0.5) vapply(streamTimeIndex(w), function(t) t[1], numeric(1))a <- PhysioExperiment(S4Vectors::SimpleList(raw = matrix(rnorm(200), 100, 2)), samplingRate = 100) b <- PhysioExperiment(S4Vectors::SimpleList(raw = matrix(rnorm(500), 250, 2)), samplingRate = 250) mpe <- MultiPhysioExperiment(streams = list(a = a, b = b), offsets = c(a = 0, b = 0.2)) w <- timeWindow(mpe, 0.3, 0.5) vapply(streamTimeIndex(w), function(t) t[1], numeric(1))
Selects the trial's span with timeWindow, so the selection, the
boundary tolerance, the clock and the provenance all follow the same rules as
any other window.
trial(x, id, streams = NULL, ...)trial(x, id, streams = NULL, ...)
x |
A |
id |
Trial identifier. |
streams |
Optional stream names to keep. |
... |
Passed to |
A MultiPhysioExperiment covering the trial.
A trial is usually captured by more than one stream, and they need not cover
it equally: one may have a dropout the others do not. This reports
streamCoverage for each stream the trial's intervals name, so a
caller can see whether a cross-stream comparison over that trial is
defensible before making one.
trialCoverage(x, id, rule = "nominal", gap_factor = 1.5, tolerance = 1e-06)trialCoverage(x, id, rule = "nominal", gap_factor = 1.5, tolerance = 1e-06)
x |
A |
id |
Trial identifier. |
rule, gap_factor
|
Passed to |
tolerance |
Coverage difference below which the streams count as agreeing. |
The returned table carries a consistent attribute: FALSE when
the streams do not agree about how much of the trial they cover. Disagreement
is surfaced rather than resolved – which stream to trust is not something this
function can decide.
A data frame with one row per stream: stream, start,
end, n_present, n_expected, coverage,
n_gaps and n_unusable_carried_gaps – dropouts an earlier
window recorded that this query cannot re-derive, and which therefore leave
completeness undecided rather than confirmed.
streamCoverage, trialIntervals
The time span each trial occupies, per recording and per stream. Because the
same trial can be captured by several devices with different spans, the
interval table is keyed on
(subject_id, session_id, trial_id, recording_id, stream).
trialIntervals(x) trialIntervals(x, allow_overlap = FALSE) <- valuetrialIntervals(x) trialIntervals(x, allow_overlap = FALSE) <- value
x |
A |
allow_overlap |
Overlapping intervals on the same recording and stream are refused by default, because two trials claiming the same samples is usually a mistake in the table rather than a property of the experiment. Pass a non-empty character reason to allow them; the reason is kept on the table so the decision is visible later. |
value |
A data frame with the five key columns plus |
An interval that contains a gap is stored: the trial happened, and
refusing it would erase that. Whether the span can be analysed is a separate
question, answered by streamCoverage at the point of use.
Invalid input is refused: reversed or non-finite bounds, an unknown stream, a
duplicate key, or an interval lying wholly outside the recording.
The interval table, or the modified container.
The trial table records that a trial happened. It is keyed on
(subject_id, session_id, trial_id) and is unique on that composite:
trial_id alone is not assumed unique across subjects.
trials(x) trials(x) <- valuetrials(x) trials(x) <- value
x |
A |
value |
A data frame with |
A trial that took place outside the recording is carried here with
observed = FALSE rather than as an interval with out-of-range times.
The trial table, or the modified container.
When each trial is its own recording, the trials belong to one session but the signals live in separate containers. A trial set holds those containers alongside the map that says which trial each one carries and how the recordings are placed relative to one another.
trialSet(recordings = list(), map = NULL)trialSet(recordings = list(), map = NULL)
recordings |
A named list of |
map |
A data frame with |
No common time axis is fabricated. Each recording keeps its own clock, and
the second does not start where the first left off. Whether elapsed time
between trials can be computed is decided by time_correspondence in the
map, exactly as for recordingMap on a single container.
Every recording_id in the map must name a recording that is actually
held; a map referring to a recording kept elsewhere is the situation this
structure exists to end.
An object of class physio_trial_set.
recordings, recordingMap,
elapsedBetweenTrials
rec <- function() MultiPhysioExperiment(emg = PhysioExperiment( assays = list(raw = matrix(rnorm(100), 50, 2)), samplingRate = 50)) ts <- trialSet( recordings = list(R1 = rec(), R2 = rec()), map = data.frame(subject_id = "P1", session_id = "S1", trial_id = c("T1", "T2"), recording_id = c("R1", "R2"), time_correspondence = "measured", reference = "trigger", offset = c(0, 12.5))) elapsedBetweenTrials(ts, "T1", "T2")rec <- function() MultiPhysioExperiment(emg = PhysioExperiment( assays = list(raw = matrix(rnorm(100), 50, 2)), samplingRate = 50)) ts <- trialSet( recordings = list(R1 = rec(), R2 = rec()), map = data.frame(subject_id = "P1", session_id = "S1", trial_id = c("T1", "T2"), recording_id = c("R1", "R2"), time_correspondence = "measured", reference = "trigger", offset = c(0, 12.5))) elapsedBetweenTrials(ts, "T1", "T2")
The circular analogue of a one-way ANOVA: tests whether two or more groups of angles share a common mean direction (assuming von Mises data of similar concentration). Use it to compare, e.g., coupling angles between limbs, speeds or groups.
watsonWilliamsTest(angles, group = NULL, units = c("degrees", "radians"))watsonWilliamsTest(angles, group = NULL, units = c("degrees", "radians"))
angles |
Numeric vector of angles, or a list of per-group angle vectors. |
group |
Grouping factor (length |
units |
|
an htest: F statistic (concentration-corrected), df and p.value.
Warns when the pooled concentration is low (rbar < 0.45), where the test
is unreliable.
Watson GS, Williams EJ (1956); Zar JH (1999) eq. 27.9.
set.seed(2) g1 <- rnorm(25, 20, 10); g2 <- rnorm(25, 60, 10) watsonWilliamsTest(list(g1, g2))$p.value # differ -> smallset.seed(2) g1 <- rnorm(25, 20, 10); g2 <- rnorm(25, 60, 10) watsonWilliamsTest(list(g1, g2))$p.value # differ -> small
The waveform analogue of a reliability coefficient (Kadaba et al. 1989): how
similar a set of repeated curves are, relative to the curve's own variation.
With groups = NULL the rows of x are repeated trials and the result is the
within-day repeatability; pass groups (e.g. a session/day label per row)
for the between-day CMC of the session-mean waveforms.
waveformCMC(x, groups = NULL)waveformCMC(x, groups = NULL)
x |
A |
groups |
Optional grouping (length |
The CMC in [0, 1] (higher = more repeatable), or NA with a warning
when the radicand is negative (waveform variation too small for a defined
CMC – a known limitation for low-excursion curves).
Kadaba MP, et al. (1989) J Orthop Res 7:849-860.
waveformICC(), waveformReliability()
base <- sin(seq(0, 2 * pi, length.out = 101)) trials <- t(sapply(1:5, function(i) base + rnorm(101, 0, 0.02))) waveformCMC(trials) # ~ 1 (repeatable)base <- sin(seq(0, 2 * pi, length.out = 101)) trials <- t(sapply(1:5, function(i) base + rnorm(101, 0, 0.02))) waveformCMC(trials) # ~ 1 (repeatable)
The reliability curve: the between-subject ICC computed frame-by-frame from
repeated trials, using the ecosystem's icc() at each cycle point.
It shows where along the movement a measurement is reliable.
waveformICC(x, model = "twoway", type = "agreement", unit = "single")waveformICC(x, model = "twoway", type = "agreement", unit = "single")
x |
A |
model, type, unit
|
Passed to |
a waveform_icc list: icc, ci_lower, ci_upper (per frame),
mean_icc, min_icc.
waveformReliability(), waveformCMC()
set.seed(1) subs <- lapply(1:8, function(s) { base <- s + sin(seq(0, 2 * pi, length.out = 101)) # subject offset = signal t(sapply(1:3, function(k) base + rnorm(101, 0, 0.1))) }) waveformICC(subs)$mean_icc # high (subjects separable)set.seed(1) subs <- lapply(1:8, function(s) { base <- s + sin(seq(0, 2 * pi, length.out = 101)) # subject offset = signal t(sapply(1:3, function(k) base + rnorm(101, 0, 0.1))) }) waveformICC(subs)$mean_icc # high (subjects separable)
The integrated movement-waveform reliability summary. It combines the
within-subject repeatability (per-subject Kadaba waveformCMC()) with the
between-subject pointwise ICC curve and the frame-by-frame standard error of
measurement and minimal detectable change (from sem() /
mdc(), the same definitions as the scalar clinimetrics).
waveformReliability(x, model = "twoway", type = "agreement", confidence = 0.95)waveformReliability(x, model = "twoway", type = "agreement", confidence = 0.95)
x |
A |
model, type
|
Passed to |
confidence |
Confidence level for the MDC (default 0.95). |
a waveform_reliability object with per-subject cmc, the icc,
sem, mdc curves (+ ICC CIs), and scalar summaries (mean_cmc,
mean_icc, peak_mdc, ...). The SEM curve is the between-subject SD at each
frame times sqrt(1 - ICC); the MDC curve is the 95% minimal detectable
change in the measurement's own units.
Kadaba MP, et al. (1989) J Orthop Res 7:849-860; Weir JP (2005) J Strength Cond Res 19:231-240 (SEM/MDC).
set.seed(1) subs <- lapply(1:10, function(s) { base <- s + 5 * sin(seq(0, 2 * pi, length.out = 101)) t(sapply(1:3, function(k) base + rnorm(101, 0, 0.3))) }) r <- waveformReliability(subs) r$mean_cmc; r$mean_icc; r$peak_mdcset.seed(1) subs <- lapply(1:10, function(s) { base <- s + 5 * sin(seq(0, 2 * pi, length.out = 101)) t(sapply(1:3, function(k) base + rnorm(101, 0, 0.3))) }) r <- waveformReliability(subs) r$mean_cmc; r$mean_icc; r$peak_mdc
When an operation constructs a NEW PhysioExperiment from an input
(rather than modifying it in place), use this to copy the input's provenance
onto the result and append the current step in one call.
withProvenance( from, to, step, params = list(), package = NA_character_, version = NA_character_ )withProvenance( from, to, step, params = list(), package = NA_character_, version = NA_character_ )
from |
The source object whose provenance should be carried forward. |
to |
The newly derived object. |
step, params, package, version
|
As in |
to carrying from's provenance plus the new step.
recordActivity for the expression-wrapping form.
from <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) from <- logStep(from, "import") to <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) to <- withProvenance(from, to, "resample", params = list(to = 50)) provenance(to)from <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) from <- logStep(from, "import") to <- PhysioExperiment( S4Vectors::SimpleList(raw = matrix(rnorm(20), 10, 2)), samplingRate = 100) to <- withProvenance(from, to, "resample", params = list(to = 50)) provenance(to)
Computes the weighted phase-lag index (wPLI) and its unbiased (debiased)
estimator from the imaginary part of a cross-spectrum, following Vinck et al.
(2011, Eq. 6). This is the single source of the wPLI debiasing math shared by
PhysioEEG (eegWPLI) and PhysioCrossModal
(weightedPLI), so the two agree exactly on identical input.
wpliEstimate(imag, debiased = TRUE)wpliEstimate(imag, debiased = TRUE)
imag |
Numeric vector of imaginary cross-spectrum values. |
debiased |
Logical; also compute the debiased estimator (default TRUE). |
The estimators, over the imaginary cross-spectrum values (one per
window, taper, or time sample), are
The debiased numerator and denominator subtract the diagonal self-terms, so the estimator is unbiased: for independent signals it is distributed around 0 rather than being inflated toward positive values.
A list with wpli (raw wPLI, from 0 to 1), wpli_debiased
(the debiased estimator, or NA if debiased = FALSE or fewer
than two values), and n (the number of values used).
Vinck, M., Oostenveld, R., van Wingerden, M., Battaglia, F., & Pennartz, C.M.A. (2011). "An improved index of phase-synchronization for electrophysiological data in the presence of volume-conduction, noise and sample-size bias." NeuroImage, 55(4), 1548-1565. doi:10.1016/j.neuroimage.2011.01.055
set.seed(1) wpliEstimate(rnorm(500))set.seed(1) wpliEstimate(rnorm(500))