Package 'PhysioNeurophys'

Title: TMS and Peripheral Motor Neurophysiology Analysis
Description: Provides transcranial magnetic stimulation (TMS) and peripheral motor-neurophysiology analysis for PhysioExperiment objects. Includes motor-evoked-potential amplitude and latency, Boltzmann recruitment curves, H-reflex recruitment and Hmax/Mmax metrics, F-wave persistence and latency, paired-pulse inhibition and facilitation, cortical silent-period timing, TMS-EEG pulse removal, source-informed SSP-SIR and SOUND cleaning, TMS-evoked-potential summaries, the PREP2 upper-limb stroke-prognosis algorithm, and a governed TMS pulse and intensity metadata schema.
Authors: Yusuke Matsui [aut, cre]
Maintainer: Yusuke Matsui <[email protected]>
License: MIT + file LICENSE
Version: 0.4.1
Built: 2026-10-03 13:41:47 UTC
Source: https://github.com/x-biosignal/PhysioNeurophys

Help Index


Measure the cortical silent period

Description

Detects sustained suppression and recovery of rectified tonic EMG after a TMS pulse using a baseline-relative threshold.

Usage

corticalSilentPeriod(
  x,
  search_window_ms = c(50, 400),
  epoch_start_ms = 0,
  baseline_window_ms = NULL,
  threshold_fraction = 0.25,
  min_silence_ms = 10,
  min_return_ms = 5,
  channel = 1,
  assay_name = NULL
)

Arguments

x

An epoched tonic-EMG PhysioExperiment.

search_window_ms

Post-stimulus CSP search window.

epoch_start_ms

Time of the first epoch sample relative to the pulse.

baseline_window_ms

Optional quiet-reference interval. The default uses all pre-stimulus samples.

threshold_fraction

Fraction of median rectified baseline below which EMG is considered silent.

min_silence_ms

Required duration of suppression.

min_return_ms

Required duration of recovered activity.

channel

One channel label or 1-based index.

assay_name

Optional assay name.

Value

A data frame with onset, offset, and duration for each trial.

References

Rossini PM, Burke D, Chen R, et al. (2015). Non-invasive electrical and magnetic stimulation of the brain, spinal cord, roots and peripheral nerves: basic principles and procedures for routine clinical and research application. Clinical Neurophysiology, 126:1071-1107. doi:10.1016/j.clinph.2015.02.001

Examples

data <- array(rep(c(-1, 1), 250), c(500, 1, 1))
data[181:330, 1, 1] <- 0
pe <- PhysioExperiment(
  assays = list(raw = data),
  samplingRate = 1000
)
corticalSilentPeriod(pe, epoch_start_ms = -100)

Detect and summarize F-waves

Description

Measures late F-wave peak-to-peak amplitude and onset latency after peripheral stimulation, then reports persistence, latency dispersion, and the mean F/M amplitude ratio.

Usage

fWaveDetect(
  x,
  f_window_ms = c(20, 60),
  m_window_ms = c(2, 12),
  epoch_start_ms = 0,
  amplitude_threshold = 0.04,
  baseline_window_ms = NULL,
  threshold_sd = 3,
  min_consecutive_ms = 0.5,
  channel = 1,
  assay_name = NULL
)

Arguments

x

A PhysioExperiment with time x channels x trials data.

f_window_ms

F-wave search window relative to the stimulus, in milliseconds.

m_window_ms

Direct M-wave window relative to the stimulus, in milliseconds.

epoch_start_ms

Time of the first epoch sample relative to the stimulus.

amplitude_threshold

Minimum F-wave peak-to-peak amplitude in the assay's native unit.

baseline_window_ms

Optional latency baseline interval. The default uses all pre-stimulus samples.

threshold_sd

Baseline standard-deviation multiplier for onset.

min_consecutive_ms

Required onset-threshold duration.

channel

One channel label or 1-based index.

assay_name

Optional assay name.

Value

An f_wave_result list containing per-trial waves, a one-row summary, and analysis settings.

References

Fisher MA (2007). F-waves: physiology and clinical uses. TheScientificWorldJournal, 7:144-160. doi:10.1100/tsw.2007.49

Examples

pe <- make_mep(n_trials = 5, mep_latency_ms = 25, seed = 3)
fWaveDetect(
  pe, m_window_ms = c(10, 18), f_window_ms = c(20, 60),
  epoch_start_ms = -20
)

Retrieve TMS pulse metadata

Description

Retrieve TMS pulse metadata

Usage

getTMSpulses(x)

Arguments

x

A PhysioExperiment.

Value

A six-column data frame with one row per stored pulse, or a typed zero-row table when TMS metadata are absent.

Examples

getTMSpulses(make_mep(n_trials = 3))

Calculate the Hmax/Mmax ratio

Description

Calculate the Hmax/Mmax ratio

Usage

hMaxMMax(recruitment)

Arguments

recruitment

An H-reflex recruitment table returned by hReflexRecruitment(), or a data frame containing intensity, h_p2p, and m_p2p.

Value

A one-row data frame containing observed maxima, their lowest tied intensities, and the dimensionless Hmax/Mmax ratio.

Examples

recruitment <- data.frame(
  intensity = c(10, 20, 30),
  h_p2p = c(0.2, 1, 0.8),
  m_p2p = c(0.5, 1.5, 2)
)
hMaxMMax(recruitment)

Estimate H-reflex onset latency

Description

Uses the baseline-standard-deviation threshold and persistent-run detector from mepLatency() within an H-reflex-specific search window.

Usage

hReflexLatency(
  x,
  h_window_ms = c(20, 45),
  epoch_start_ms = 0,
  baseline_window_ms = NULL,
  threshold_sd = 3,
  min_consecutive_ms = 1,
  channel = 1,
  assay_name = NULL
)

Arguments

x

A PhysioExperiment with time x channels x trials data.

h_window_ms

H-reflex window relative to the stimulus, in milliseconds.

epoch_start_ms

Time of the first epoch sample relative to the stimulus.

baseline_window_ms

Optional baseline interval. The default uses all pre-stimulus samples.

threshold_sd

Baseline standard-deviation multiplier.

min_consecutive_ms

Required duration of a threshold crossing.

channel

One channel label or 1-based index.

assay_name

Optional assay name.

Value

A data frame containing onset sample and stimulus-relative H-reflex latency for each trial.

Examples

pe <- make_mep(n_trials = 3, mep_latency_ms = 25, seed = 2)
hReflexLatency(pe, epoch_start_ms = -20)

Measure an H-reflex recruitment series

Description

Measures peak-to-peak direct motor (M) and Hoffmann-reflex (H) responses in separate post-stimulus windows for each trial.

Usage

hReflexRecruitment(
  x,
  intensity,
  m_window_ms = c(2, 12),
  h_window_ms = c(20, 45),
  epoch_start_ms = 0,
  channel = 1,
  assay_name = NULL
)

Arguments

x

A PhysioExperiment with time x channels x trials data.

intensity

Finite stimulation intensity, one value per trial. Values remain in the caller's native stimulator unit.

m_window_ms

Direct M-wave window relative to the stimulus, in milliseconds.

h_window_ms

H-reflex window relative to the stimulus, in milliseconds.

epoch_start_ms

Time of the first epoch sample relative to the stimulus.

channel

One channel label or 1-based index.

assay_name

Optional assay name.

Value

A data frame with one row per trial and M/H peak-to-peak amplitudes and fiducial samples.

References

Palmieri RM, Ingersoll CD, Hoffman MA (2004). The Hoffmann reflex: methodologic considerations and applications for use in sports medicine and athletic training research. Journal of Athletic Training, 39:268-277.

Examples

pe <- make_mep(n_trials = 3, intensities = c(30, 40, 50), seed = 1)
hReflexRecruitment(
  pe, c(10, 20, 30),
  m_window_ms = c(10, 18), h_window_ms = c(20, 60),
  epoch_start_ms = -20
)

Estimate the H-reflex recruitment threshold

Description

Finds the lowest stimulation intensity whose mean H amplitude reaches an absolute cutoff or a fraction of the observed Mmax.

Usage

hReflexThreshold(recruitment, criterion = 0.05, scale = c("mmax", "absolute"))

Arguments

recruitment

An H-reflex recruitment table returned by hReflexRecruitment(), or a data frame containing intensity, h_p2p, and m_p2p.

criterion

Non-negative absolute amplitude, or a fraction in ⁠[0, 1]⁠ when scale = "mmax".

scale

Whether criterion is relative to Mmax or in native amplitude units.

Value

A one-row data frame containing the first qualifying intensity, applied cutoff, and scale.

Examples

recruitment <- data.frame(
  intensity = c(10, 20, 30),
  h_p2p = c(0.1, 0.5, 1),
  m_p2p = c(0.2, 0.8, 2.5)
)
hReflexThreshold(recruitment, criterion = 0.2)

Simulate epoched TMS motor-evoked potentials

Description

Generates biphasic MEP waveforms with known latency and a Boltzmann amplitude-intensity relationship.

Usage

make_mep(
  n_time = 600,
  n_channels = 1,
  n_trials = 12,
  sr = 5000,
  epoch_start_ms = -20,
  intensities = NULL,
  plateau = 2,
  s50 = 50,
  k = 5,
  mep_latency_ms = 20,
  mep_dur_ms = 10,
  baseline_sd = 0.02,
  seed = NULL
)

Arguments

n_time

Number of samples per epoch.

n_channels

Number of MEP channels.

n_trials

Number of TMS trials.

sr

Sampling rate in Hz.

epoch_start_ms

Time of the first sample relative to the TMS pulse.

intensities

Per-trial stimulation intensity in ⁠%MSO⁠.

plateau, s50, k

Boltzmann recruitment parameters.

mep_latency_ms

Planted MEP onset latency.

mep_dur_ms

Duration of the one-cycle biphasic waveform.

baseline_sd

Gaussian baseline-noise standard deviation.

seed

Optional random seed.

Value

An epoched PhysioExperiment with TMS pulse metadata.

Examples

pe <- make_mep(n_trials = 5, seed = 1)
dim(SummarizedExperiment::assay(pe))
getTMSpulses(pe)

Measure motor-evoked-potential amplitude

Description

Calculates peak-to-peak MEP amplitude within a response window for every selected channel and trial.

Usage

mepAmplitude(
  x,
  response_window_ms = c(10, 60),
  epoch_start_ms = 0,
  channels = NULL,
  assay_name = NULL
)

Arguments

x

A PhysioExperiment with time x channels x trials MEP data.

response_window_ms

Two response-window limits relative to the TMS pulse, in milliseconds.

epoch_start_ms

Time of the first epoch sample relative to the pulse.

channels

Optional channel labels or 1-based indices.

assay_name

Optional assay name.

Value

A data frame with one row per selected channel and trial.

References

Rossini PM, Burke D, Chen R, et al. (2015). Non-invasive electrical and magnetic stimulation of the brain, spinal cord, roots and peripheral nerves: basic principles and procedures for routine clinical and research application. Clinical Neurophysiology, 126:1071-1107. doi:10.1016/j.clinph.2015.02.001

Examples

pe <- make_mep(n_trials = 4, seed = 1)
mepAmplitude(pe, epoch_start_ms = -20)

Estimate motor-evoked-potential onset latency

Description

Detects the first persistent signed deviation from the baseline mean above a multiple of the baseline standard deviation.

Usage

mepLatency(
  x,
  response_window_ms = c(5, 50),
  epoch_start_ms = 0,
  baseline_window_ms = NULL,
  threshold_sd = 3,
  min_consecutive_ms = 1,
  channels = NULL,
  assay_name = NULL
)

Arguments

x

A PhysioExperiment with time x channels x trials MEP data.

response_window_ms

Search window relative to the TMS pulse.

epoch_start_ms

Time of the first epoch sample relative to the pulse.

baseline_window_ms

Optional baseline interval. The default uses all pre-stimulus samples.

threshold_sd

Baseline standard-deviation multiplier.

min_consecutive_ms

Required duration of a threshold crossing.

channels

Optional channel labels or 1-based indices.

assay_name

Optional assay name.

Value

A data frame containing onset sample and latency for each selected channel and trial.

Examples

pe <- make_mep(n_trials = 4, intensities = rep(65, 4), seed = 2)
mepLatency(pe, epoch_start_ms = -20)

Summarize paired-pulse MEP responses

Description

Compares conditioned motor-evoked-potential amplitudes with the aggregate unconditioned test response at each interstimulus interval (ISI).

Usage

pairedPulse(
  x,
  condition,
  isi_ms,
  response_window_ms = c(10, 60),
  epoch_start_ms = 0,
  channel = 1,
  assay_name = NULL,
  aggregate = c("mean", "median")
)

Arguments

x

An epoched PhysioExperiment containing MEP trials.

condition

Per-trial labels, exactly "test" or "conditioned".

isi_ms

Per-trial interstimulus interval in milliseconds. Use NA for test trials and a positive finite value for conditioned trials.

response_window_ms

MEP response window relative to the test pulse.

epoch_start_ms

Time of the first epoch sample relative to the test pulse.

channel

One channel label or 1-based index.

assay_name

Optional assay name.

aggregate

Whether to summarize amplitudes by the mean or median.

Value

A data frame with one row per conditioned ISI and conditioned/test amplitudes, their ratio, inhibition, and facilitation.

References

Kujirai T, Caramia MD, Rothwell JC, et al. (1993). Corticocortical inhibition in human motor cortex. Journal of Physiology, 471:501-519. doi:10.1113/jphysiol.1993.sp019912

Examples

pe <- make_mep(
  n_trials = 6,
  intensities = rep(50, 6),
  baseline_sd = 0,
  seed = 1
)
pairedPulse(
  pe,
  condition = c("test", "test", rep("conditioned", 4)),
  isi_ms = c(NA, NA, 2, 2, 10, 10),
  epoch_start_ms = -20
)

Apply the PREP2 upper-limb prognosis algorithm

Description

Implements the day-3 PREP2 decision tree from SAFE score, age, motor-evoked potential status, and NIH Stroke Scale score.

Usage

prep2(safe_score, age, mep_status = NULL, nihss = NULL)

Arguments

safe_score

Shoulder Abduction and Finger Extension MRC sum, an integer from 0 to 10.

age

Age in years.

mep_status

Optional MEP status: logical, "present"/"MEP+", or "absent"/"MEP-".

nihss

Optional day-3 NIHSS total, an integer from 0 to 42.

Value

A prep2_result containing category, decision pathway, inputs, and a clinical description.

References

Stinear CM, Byblow WD, Ackerley SJ, Smith MC, Stinear JW, Barber PA (2017). PREP2: A biomarker-based algorithm for predicting upper limb function after stroke. Annals of Clinical and Translational Neurology, 4:811-820. doi:10.1002/acn3.488

Examples

prep2(safe_score = 8, age = 65)
prep2(2, 70, mep_status = "absent", nihss = 5)

Fit a Boltzmann MEP recruitment curve

Description

Fits peak-to-peak MEP amplitude against stimulator intensity with a three-parameter logistic curve.

Usage

recruitmentCurve(
  x,
  channel = 1,
  response_window_ms = c(10, 60),
  epoch_start_ms = 0,
  intensity = NULL,
  assay_name = NULL
)

Arguments

x

An epoched MEP PhysioExperiment.

channel

One channel label or 1-based index.

response_window_ms

MEP response window in milliseconds.

epoch_start_ms

Time of the first epoch sample relative to the pulse.

intensity

Optional per-trial stimulation intensity in ⁠%MSO⁠.

assay_name

Optional assay name.

Value

A recruitment_curve object with fitted parameters, predictions, fit quality, and the underlying nls model.

References

Devanne H, Lavoie BA, Capaday C (1997). Input-output properties and gain changes in the human corticospinal pathway. Experimental Brain Research, 114:329-338. doi:10.1007/PL00005641

Examples

pe <- make_mep(n_trials = 15, baseline_sd = 0.001, seed = 3)
recruitmentCurve(pe, epoch_start_ms = -20)

Remove TMS pulse and recharge intervals

Description

Replaces sample-exact closed pulse/recharge intervals by a linear or cubic Hermite bridge, or blanks them to zero or a trial-specific baseline. The selected input assay is preserved unless overwrite = TRUE.

Usage

removeTMSpulse(
  x,
  pulse_window_ms = c(-2, 10),
  recharge_windows_ms = NULL,
  method = c("cubic", "linear", "blank"),
  support_ms = 2,
  blank_value = c("baseline", "zero"),
  baseline_window_ms = c(-200, -20),
  epoch_start_ms = 0,
  assay_name = NULL,
  output_assay = "tms_pulse_clean",
  overwrite = FALSE
)

Arguments

x

A PhysioExperiment with time x channel or time x channel x trial data.

pulse_window_ms

Increasing pulse-window limits in milliseconds.

recharge_windows_ms

Optional increasing pair or n x 2 matrix.

method

Exactly "cubic", "linear", or "blank".

support_ms

One positive derivative-support duration for cubic interpolation, in milliseconds.

blank_value

Exactly "baseline" or "zero".

baseline_window_ms

Closed baseline interval in milliseconds.

epoch_start_ms

Time of the first sample relative to the pulse.

assay_name

Optional input assay name.

output_assay

Output assay name.

overwrite

Whether to overwrite the selected input assay.

Details

Closed intervals use round((time_ms - epoch_start_ms) / 1000 * sampling_rate) + 1. Overlapping or sample-adjacent pulse/recharge intervals are merged. Linear and cubic methods require real samples on both sides and never bridge across a second removed interval. Baseline settings do not affect interpolation or zero blanking. Baseline blanking requires at least two samples wholly outside every removed interval. The audit metadata contains the complete altered mask, merged sample ranges, continuity jumps, and robust baseline noise.

Value

A modified PhysioExperiment with an appended TMS-EEG audit step.

References

Rogasch NC, Sullivan C, Thomson RH, et al. (2017). Analysing concurrent transcranial magnetic stimulation and electroencephalographic data. NeuroImage, 147:934-951. doi:10.1016/j.neuroimage.2016.10.031


Store TMS pulse metadata

Description

Stores one pulse row per trial without replacing other experiment metadata. Intensity and resting motor threshold are expressed as percent of maximum stimulator output (⁠%MSO⁠).

Usage

setTMSpulses(
  x,
  intensity_pct_mso,
  target = NA_character_,
  coil = NA_character_,
  rmt_pct_mso = NA_real_,
  onset_sec = NA_real_
)

Arguments

x

A PhysioExperiment with a 2-D or epoched 3-D assay.

intensity_pct_mso

Numeric stimulation intensity, one value per trial.

target

Cortical target or target-muscle label.

coil

Coil descriptor.

rmt_pct_mso

Resting motor threshold in ⁠%MSO⁠.

onset_sec

Pulse onset in the source continuous recording, in seconds.

Value

The modified PhysioExperiment.

Examples

pe <- make_mep(n_trials = 3, intensities = c(40, 50, 60))
pe <- setTMSpulses(pe, c(40, 50, 60), target = "M1_FDI")
getTMSpulses(pe)

Summarize short-interval inhibition and intracortical facilitation

Description

Summarize short-interval inhibition and intracortical facilitation

Usage

siciIcf(paired, sici_range_ms = c(1, 5), icf_range_ms = c(7, 20))

Arguments

paired

A table returned by pairedPulse() containing isi_ms, n_conditioned, and ratio.

sici_range_ms

Closed SICI ISI range in milliseconds.

icf_range_ms

Closed ICF ISI range in milliseconds.

Value

A one-row data frame with conditioned-trial-weighted SICI and ICF ratios, percentages, and trial counts.

Examples

paired <- data.frame(
  isi_ms = c(2, 3, 10, 15),
  n_conditioned = rep(2L, 4),
  ratio = c(0.4, 0.5, 1.5, 1.4)
)
siciIcf(paired)

Clean TMS-EEG sensor noise with SOUND

Description

Implements simultaneous leave-one-sensor noise estimation followed by the source-space Wiener reconstruction of the SOUND algorithm.

Usage

soundClean(
  x,
  forward_model,
  lambda = 0.1,
  iterations = 10L,
  tolerance = 0.01,
  reference = "average",
  analysis_window_ms = NULL,
  epoch_start_ms = 0,
  assay_name = NULL,
  output_assay = "tms_sound",
  overwrite = FALSE
)

Arguments

x

A pulse-cleaned PhysioExperiment.

forward_model

A list containing a finite channel-matched leadfield.

lambda

Positive source-reconstruction regularization.

iterations

Maximum number of complete simultaneous updates.

tolerance

Non-negative maximum relative noise change for convergence.

reference

Currently exactly "average".

analysis_window_ms

Optional closed noise-estimation interval. NULL uses all samples except recorded pulse/recharge gaps.

epoch_start_ms

Time of the first epoch sample relative to the pulse.

assay_name

Optional pulse-cleaned input assay.

output_assay

Output assay name.

overwrite

Whether to overwrite the selected input assay.

Details

SOUND assumes diagonal sensor noise, an approximate channel-matched lead field, and i.i.d. source amplitudes for its regularized reconstruction. All channel noise estimates are updated simultaneously from the preceding round, and one final cleaning matrix is applied to every sample and trial. Pulse samples are excluded from noise estimation. Regularization is not a significance threshold and is not optimized against the reported TEP peaks.

Value

A modified PhysioExperiment with the fixed SOUND cleaning matrix, complete noise history, and convergence diagnostics.

References

Mutanen TP, Metsomaa J, Liljander S, Ilmoniemi RJ (2018). Automatic and robust noise suppression in EEG and MEG: The SOUND algorithm. NeuroImage, 166:135-151. doi:10.1016/j.neuroimage.2017.10.021


Average TMS-evoked potentials and measure canonical peaks

Description

Baseline-corrects every trial and channel before a mean or trimmed mean, then finds signed peaks independently in each requested channel.

Usage

tepAverage(
  x,
  components = c("N15", "P30", "N45", "P60", "N100", "P180"),
  windows_ms = NULL,
  channels = NULL,
  baseline_window_ms = c(-200, -20),
  epoch_start_ms = 0,
  average = c("mean", "trimmed"),
  trim = 0.2,
  assay_name = NULL
)

Arguments

x

A PhysioExperiment containing epoched TMS-EEG.

components

Exact canonical component names in requested order.

windows_ms

Optional named component x 2 override matrix.

channels

Optional exact labels or 1-based indices.

baseline_window_ms

Closed baseline interval.

epoch_start_ms

Time of the first sample relative to the pulse.

average

Exactly "mean" or "trimmed".

trim

Trim fraction in ⁠[0, 0.5)⁠.

assay_name

Optional assay name.

Details

Default signed peak windows are N15 (10–20 ms), P30 (20–40 ms), N45 (35–55 ms), P60 (50–75 ms), N100 (80–140 ms), and P180 (140–220 ms). Exact ties use the earliest sample and a peak on a window endpoint is marked as a boundary diagnostic. Canonical names define measurement windows only. Auditory and somatosensory responses can remain, and no component is evidence of a verified cortical source.

Value

A tms_tep list with waveform, component, and settings tables.

References

Rogasch NC, Sullivan C, Thomson RH, et al. (2017). Analysing concurrent transcranial magnetic stimulation and electroencephalographic data. NeuroImage, 147:934-951. doi:10.1016/j.neuroimage.2016.10.031


Clean TMS-EEG muscle artifact with SSP-SIR

Description

Estimates one deterministic artifact subspace across trials and reconstructs the retained activity through a channel-matched lead field.

Usage

tmsSSPSIR(
  x,
  forward_model,
  artifact_window_ms = c(5, 50),
  n_artifact = NULL,
  variance_fraction = 0.9,
  lambda = 0.05,
  reference = "average",
  epoch_start_ms = 0,
  assay_name = NULL,
  output_assay = "tms_sspsir",
  overwrite = FALSE
)

Arguments

x

A pulse-cleaned PhysioExperiment.

forward_model

A list containing a finite channel-matched leadfield.

artifact_window_ms

Closed artifact-training interval.

n_artifact

Optional exact number of artifact components.

variance_fraction

Cumulative artifact variance target when n_artifact is NULL.

lambda

Positive source-reconstruction regularization.

reference

Currently exactly "average".

epoch_start_ms

Time of the first epoch sample relative to the pulse.

assay_name

Optional pulse-cleaned input assay.

output_assay

Output assay name.

overwrite

Whether to overwrite the selected input assay.

Details

The pulse must already be removed or hardware absence must be explicitly declared in metadata(x)$tms_eeg$pulse_absent. Both data and lead field are average referenced with the same matrix. The returned data use the fixed source-informed reconstruction ⁠Lr G P⁠, not the plain SSP projection P. SSP-SIR can attenuate neural signal when the artifact and neural subspaces overlap; a lead field is an approximate physical model, not proof that a retained deflection is cortical.

Value

A modified PhysioExperiment with fixed SSP-SIR reconstruction metadata.

References

Mutanen TP, Kukkonen M, Nieminen JO, et al. (2016). Recovering TMS-evoked EEG responses masked by muscle artifacts. NeuroImage, 139:157-166. doi:10.1016/j.neuroimage.2016.05.028