Fits the rank-1 GLM of Pedregosa et al. (2015): within each voxel one HRF,
expressed in an HRF basis, is shared by all trials, and each trial has its
own amplitude. With model = "separate" (R1-GLMS, the default and the best
performer in that paper) every trial is fitted in its own least-squares
separate (LSS) model, so the amplitudes are LSS estimates under the
voxel's estimated HRF. With model = "joint" (R1-GLM) all trials enter one
least-squares-all model.
Arguments
- Y
Numeric matrix of BOLD data (time x voxels).
- events
Data frame with
onset,durationandconditioncolumns (andrunfor multi-run sampling frames, with run-relative onsets), as forestimate_voxel_hrf(). Each row is one trial. Conditions are labels only: all trials share each voxel's HRF.- basis
An
fmrihrfHRF basis, e.g.fmrihrf::HRF_SPMG3or an FIR basis fromfmrihrf::hrf_fir_generator()/fmrihrf::HRF_FIR.- sframe
An
fmrihrfsampling frame withnrow(Y)scans.- nuisance_regs
Optional numeric matrix of nuisance regressors.
- fixed_regs
Optional numeric matrix of fixed regressors (run intercepts are added when not already spanned).
- model
"separate"(R1-GLMS) or"joint"(R1-GLM).- trial_groups
Optional vector with one condition label per trial (row of
events), e.g.events$condition, formodel = "separate". Each trial-wise model then has one "other trials" regressor per group (LSS-N, as inlss()). Because the HRF is learned mostly through these group regressors, supplytrial_groupswhenever conditions may differ in mean response, in particular in sign. See Details.- init
"aggregate","reference", or a K x V numeric matrix (or length-K vector) of starting HRF coefficients.- ref_hrf
HRF used for the
"reference"initialization and to orient the sign of each estimated HRF. Defaults tofmrihrf::HRF_SPMG1.- prewhiten
Optional prewhitening options (see
prewhiten_options()). Global and run pooling are supported; the noise model is estimated with one aggregate regressor per basis function.- solver
"als"(default): exact alternating least squares, run in parallel over voxels with OpenMP."lbfgs": joint quasi-Newton optimization of HRF and amplitudes with L-BFGS-B, as in Pedregosa et al. (2015), on the same objective and starting point (serial; separate model only). See Details.- max_iter
Maximum number of alternating iterations (for
"lbfgs", at least 1000 quasi-Newton iterations are allowed).- tol
Relative objective change used as the convergence criterion (for
"lbfgs", passed asfactr = tol / .Machine$double.eps).
Value
A list with
- beta
Trial amplitudes (trials x voxels), in peak-response units.
- other
For
model = "separate", the amplitude of the pooled other-trials regressor in each trial's model (trials x voxels);NULLfor the joint model.- hrf
A VoxelHRF object with the unit-peak HRF coefficients (K x voxels), the removed
amplitude_scale,basisandsframe.- objective
Final residual sum of squares per voxel (summed over the trial-wise models for
"separate").- iterations, converged
Per-voxel iteration counts and convergence flags.
- degenerate
Voxels whose estimated HRF has no positive peak of at least 5% of its largest absolute deflection after orientation (scaled by that deflection instead, so their amplitudes are not in peak-response units). Also stored in
hrf. The policy is shared withestimate_voxel_hrf(): such voxels are flagged and reported in one warning rather than failing the fit.- model
The fitted model.
When prewhitening is applied the fitted plan is attached as the
whiten_plan attribute.
Details
For trial \(i\) with basis-convolved design block \(X_i\) (n x K) and
the sum of all blocks \(T_X\), the separate model minimizes, per voxel,
$$\sum_i \| y - \beta_i X_i h - r_i (T_X - X_i) h \|^2$$
over the HRF coefficients \(h\), trial amplitudes \(\beta\) and
other-trial amplitudes \(r\); the joint model minimizes
\(\| y - \sum_i \beta_i X_i h \|^2\). Fixed regressors (run intercepts are
added when absent) and nuisance regressors are projected from the design
and data first, which gives each trial-wise model its own confound
coefficients, as in lss(). (The original formulation shares one set of
confound coefficients across the trial-wise models.)
The fit uses exact alternating least squares rather than the quasi-Newton solver of the paper: given \(h\), the amplitudes are ordinary LSS (or LSA) estimates; given the amplitudes, \(h\) solves a K-dimensional least squares problem. Each step minimizes its block exactly, so the objective never increases. All quantities either step needs are K x K Gram blocks of the residualized design and the product \(X^\top Y\), so after that one product the separate model costs \(O(T K^2)\) per voxel and iteration, independent of the number of scans. The joint model costs \(O(T^2 K^2 + T^3)\) per voxel and iteration and is intended for regions of interest.
The problem is bilinear: \(h\) and the amplitudes are determined only up
to a common scale and sign. After fitting, each voxel's HRF is oriented to
correlate positively with ref_hrf and scaled to a unit positive peak, and
the amplitudes absorb that scale, so they are in peak-response units for
unit-amplitude, zero-duration events, like lss_with_hrf(). The returned
hrf is a VoxelHRF object and can be passed to lss_with_hrf() to
estimate trial amplitudes in new data (for example a held-out run) with the
learned HRFs.
The objective is not jointly convex. init = "aggregate" starts each voxel
from the pooled-shape fit of estimate_voxel_hrf() (one common amplitude
for all trials); init = "reference" starts every voxel from the
projection of ref_hrf onto the basis, which is more stable for voxels
whose mean response is near zero. A K x V matrix of starting coefficients
is also accepted.
References
Pedregosa, F., Eickenberg, M., Ciuciu, P., Thirion, B., & Gramfort, A. (2015). Data-driven HRF estimation for encoding and decoding models. NeuroImage, 104, 209-220.
Examples
# \donttest{
set.seed(1)
sframe <- fmrihrf::sampling_frame(blocklens = 200, TR = 1)
events <- data.frame(onset = seq(10, 180, by = 9), duration = 0,
condition = "A")
basis <- fmrihrf::HRF_SPMG3
X <- fmrilss:::.voxhrf_trial_basis(events, basis, sframe)$X
h <- c(1, 0.4, -0.2)
beta <- matrix(rnorm(nrow(events) * 5, 1, 0.3), nrow(events), 5)
Y <- X %*% kronecker(beta, h) + matrix(rnorm(200 * 5, sd = 0.5), 200, 5)
fit <- lss_rank1(Y, events, basis, sframe)
dim(fit$beta)
#> [1] 19 5
fit$hrf$coefficients[, 1]
#> basis_1 basis_2 basis_3
#> 5.217199 4.814784 -1.088945
# }