Fits a common-amplitude GLM to estimate one pooled HRF shape for every voxel. The HRF basis and response are residualized against the complete fixed and nuisance span before fitting. Estimation fails when that span makes the HRF basis unidentifiable or rank deficient.
Usage
estimate_voxel_hrf(
Y,
events,
basis,
nuisance_regs = NULL,
sframe = NULL,
fixed_regs = NULL,
ref_hrf = NULL
)Arguments
- Y
Numeric matrix of BOLD data (time x voxels).
- events
Data frame with
onset,durationandconditioncolumns. For a multi-run sampling frame, aruncolumn is required and onsets are physical times relative to that run.- basis
HRF object from the
fmrihrfpackage.- nuisance_regs
Optional finite numeric matrix of nuisance regressors.
- sframe
Explicit
fmrihrfsampling frame defining scan times and TR. Required; onset and duration values use its physical-time units.- fixed_regs
Optional finite numeric matrix of fixed/common regressors. An intercept is added when it is not already in their span.
- ref_hrf
HRF used to orient the sign of each estimated shape. Defaults to the canonical
fmrihrf::HRF_SPMG1.
Value
A VoxelHRF object containing at least:
- coefficients
Matrix of positive-peak-normalized HRF shape weights with one row per basis function and one column per voxel.
- amplitude_scale
The signed scale removed from each raw pooled-fit coefficient column.
- degenerate
Logical, one per voxel: the estimated shape has no positive peak after orientation, or one smaller than 5% of its largest absolute deflection (typically a voxel without signal). Such shapes are scaled by their largest absolute value instead, and a warning reports how many there are; estimation does not fail.
- basis
The HRF basis object used.
- conditions
Observed event labels. Labels are metadata: all events are pooled into one shape per voxel.
- condition_pooling
The literal string "all-events".
Examples
# \donttest{
set.seed(1)
Y <- matrix(rnorm(100), 50, 2)
events <- data.frame(onset = c(5, 25), duration = 1,
condition = "A")
basis <- fmrihrf::HRF_SPMG1
sframe <- fmrihrf::sampling_frame(blocklens = nrow(Y), TR = 1)
times <- fmrihrf::samples(sframe, global = TRUE)
rset <- fmrihrf::regressor_set(onsets = events$onset,
fac = factor(rep("all events", nrow(events))),
hrf = basis, duration = events$duration,
span = 30)
X <- fmrihrf::evaluate(rset, grid = times, precision = 0.1, method = "conv")
coef <- matrix(rnorm(ncol(X) * ncol(Y)), ncol(X), ncol(Y))
Y <- X %*% coef + Y * 0.1
est <- estimate_voxel_hrf(Y, events, basis, sframe = sframe)
str(est)
#> List of 9
#> $ coefficients : num [1, 1:2] 5.7 5.7
#> $ amplitude_scale : num [1:2] -0.1018 0.0121
#> $ degenerate : logi [1:2] FALSE FALSE
#> $ basis :function (t)
#> ..- attr(*, "class")= chr [1:2] "HRF" "function"
#> ..- attr(*, "name")= chr "SPMG1"
#> ..- attr(*, "nbasis")= int 1
#> ..- attr(*, "span")= num 24
#> ..- attr(*, "param_names")= chr [1:3] "P1" "P2" "A1"
#> ..- attr(*, "params")=List of 3
#> .. ..$ P1: num 5
#> .. ..$ P2: num 15
#> .. ..$ A1: num 0.00833
#> $ conditions : chr "A"
#> $ sframe :List of 4
#> ..$ blocklens : int 50
#> ..$ TR : num 1
#> ..$ start_time: num 0.5
#> ..$ precision : num 0.1
#> ..- attr(*, "class")= chr "sampling_frame"
#> $ condition_pooling: chr "all-events"
#> $ normalization : chr "positive-peak"
#> $ coefficient_units: chr "unit-peak HRF shape weights"
#> - attr(*, "class")= chr "VoxelHRF"
# }