Skip to contents

Creates a regressor from a continuously sampled feature (for example RMS energy of an acoustic stimulus) by treating each sample as a zero-order-hold bin of width \(\Delta t\). The result is the Riemann-sum / ZOH approximation of convolving the feature with an HRF, not a train of unit-mass impulses.

Usage

feature_regressor(
  values,
  hrf = HRF_SPMG1,
  times = NULL,
  dt = NULL,
  start = 0,
  center = TRUE,
  scale = c("none", "sd"),
  mask = NULL,
  span = NULL
)

Arguments

values

Numeric vector of feature samples.

hrf

The hemodynamic response function to convolve with the feature. Same types as [regressor()], except a list of per-event HRFs is not allowed. Defaults to `HRF_SPMG1`.

times

Numeric vector of sample times in seconds, same length as `values`. Mutually exclusive with `dt`. Times must be strictly increasing and non-negative. The last bin width is the last inter-sample gap.

dt

Positive sampling interval in seconds. Mutually exclusive with `times`. Sample times are `start + seq(0, by = dt, length.out = length(values))`.

start

Start time in seconds used only when `dt` is supplied. Defaults to 0.

center

Logical; if `TRUE` (default), subtract the mean of the (masked) samples before convolution.

scale

Character; `"none"` (default) leaves native units, `"sd"` divides by the standard deviation of the (masked) samples after centering.

mask

Optional logical vector the same length as `values`. Center and scale statistics are computed on `mask == TRUE` samples only; off-mask samples are set to 0 after that (block-centered modulator).

span

Temporal window in seconds for the HRF, passed to [regressor()]. If `NULL`, the HRF's own span is used.

Value

An S3 object of class `c("FeatureReg", "Reg", "list")`. Evaluation uses the same convolution path as [regressor()].

Details

Centering and scaling are applied to the feature **before** convolution. The default is to demean and leave the native units unchanged. This is the usual choice when the feature is defined for a whole run: the mean aliases into the intercept, and the edge transients of a non-zero mean are rarely of interest. If the feature is a within-block modulator, pass a `mask` for the on-period (and typically a separate boxcar for "stimulus on") rather than demeaning the concatenated series.

This is **not** parametric modulation of discrete events. No unmodulated companion regressor is added. Zeros are valid samples and are retained.

Evaluate with `precision` less than or equal to the feature sampling interval so that several samples are not collapsed into one convolution bin. Compared with `regressor(times, amplitude = values, duration = 0)`, the predicted BOLD is smaller by about \(\Delta t\) (the missing integral measure of a continuous signal).

See also

[regressor()], [evaluate()]

Examples

# 10 Hz envelope over 8 seconds, demeaned
dt <- 0.1
t <- seq(0, 8, by = dt)
rms <- abs(sin(2 * pi * t / 4))
feat <- feature_regressor(rms, dt = dt, hrf = HRF_SPMG1)

grid <- seq(0, 12, by = 1)
y <- evaluate(feat, grid, precision = dt)

# Same ZOH encoding as a duration-dt event regressor (no centering)
feat_raw <- feature_regressor(rms, dt = dt, center = FALSE, scale = "none")
ev <- regressor(t, HRF_SPMG1, duration = dt, amplitude = rms)
all.equal(evaluate(feat_raw, grid, precision = dt),
          evaluate(ev, grid, precision = dt))
#> [1] TRUE