Changelog
Source:NEWS.md
fmrireg 0.2.0
HRF Estimation
-
estimate_hrf()is now a vectorized, condition-level smooth FIR estimator. It constructs an explicit event-aligned spline basis, removes baseline and fixed nuisance designs once, fits all voxels with one penalized multiresponse solve, and can choose a shared smoothing strength by scale-normalized GCV. The newfmri_hrf_estimateresult preserves curve and voxel labels and provides standard errors, confidence intervals,tidy(),predict(),coef(), andas.matrix()methods. This replaces a voxel-by-voxel GAM path that treated convolved design values as if they were post-stimulus time and failed before prediction.
Statistical Corrections
-
AR degrees of freedom.
fmri_lm()no longer deflates the residual degrees of freedom when an AR structure is used. The previous adjustment multipliedn - pby1 / (1 + 2 * sum(1 - k/n)), which is the variance inflation one would obtain if every autocorrelation equalled 1. It never depended on the fitted AR coefficients — atn = 200,p = 12, AR(1) it returned 62.9 whether the true autocorrelation was 0.05 or 0.9 — and it was applied on top of prewhitening, double-counting a correction already made.This changes reported AR p-values. They become less conservative; degrees of freedom roughly triple for AR(1). The previous behaviour cost statistical power rather than inflating false positives, so results that were significant before remain significant, but p-values and any power-sensitive analyses will differ from earlier versions.
calculate_effective_df()gains a workingmethod = "satterthwaite"(previously a verbatim duplicate ofmethod = "simple") that computestr(RV)^2 / tr(RVRV)from a supplied design and post-whitening covariance, reducing exactly ton - pwhen the errors are uncorrelated. Residual correlation surviving the filter is what legitimately costs degrees of freedom; AR order by itself does not.
Bug Fixes
Shared AR estimation now pools voxel residual autocovariances by default instead of fitting the cross-voxel mean residual series. The former targets a typical voxel covariance; the latter suppresses voxel-specific noise and targets a different, often more autocorrelated coherent component. The old behavior remains available explicitly as
noise_spec(..., shared_estimator = "mean_series"). Fixed-order fits now use fmriAR’s pooled AR autocovariance path as well; the previous ARMA(p, 0) shortcut accidentally collapsed both choices to the mean series.shared_estimator = "mean_series"now retains the matching OLS design-bias correction. OLS projection is linear across response columns, so averaging residuals after projection is exactly the same as projecting the mean series.The OLS residual-bias correction now uses a separate covariance-tail lag budget rather than stopping at the fitted AR order. Projection mixes tail autocovariances into lags 0:p, so a p-lag correction left avoidable bias.
Global AR estimation over separately fitted runs now supplies the exact block-diagonal residual-forming design. Row-binding the per-run designs incorrectly described a single coefficient vector shared across runs.
Design-corrected AR coefficients are estimated once from initial OLS residuals and held fixed for the GLS solve. Later GLS residuals have a different residual-forming operator and no longer reuse the OLS
design=correction. The low-rank engine now follows this contract too, and the low-rank and RRR whitening paths reset at run boundaries.GDS exports now release unreachable HDF5 handles before atomic finalization, allowing Windows to move and immediately reopen the completed file.
write_results(strategy = "by_stat")no longer scatters contrast maps onto the wrong voxels..compute_statistical_volumes()calledas.logical()on the mask, which dropsdimfor plain arrays (the type.fmri_dataset_mask_space()always supplies), sowhich(..., arr.ind = TRUE)returned linear indices instead of 3D coordinates.Oversized residual-bootstrap blocks now remain one contiguous temporal block instead of silently becoming interleaved odd/even samples.
Mixed-model solver failures now warn and return
NAcoefficients rather than plausible zeros; malformed response dimensions fail before solver dispatch.robust_psinow has an effect. It was previously unreachable:robustdefaulted toFALSErather thanNULL, sorobust_options$typewas always claimed beforerobust_psiwas consulted.robust’s default is nowNULL, which also makes “unspecified” distinguishable from “explicitly off”.An explicit
robust = FALSEis no longer silently overridden byrobust_options = list(type = "huber"); the combination is now an error.Supplying
cfgalongside other configuration arguments is now an error instead of silently discarding them. Previouslycor_struct = "ar2"with acfgnaming"iid"ran IID without warning.AR shorthands (
cor_struct,cor_iter,cor_global,ar1_exact_first,ar_p,ar_voxelwise) that disagree with the correspondingar_optionsentry now error rather than being silently dropped. Shorthands that agree are still accepted.enginenow warns about the execution arguments it ignores (strategy,nchunks,use_fast_path,progress,parallel_voxels,parallel_chunks), which were previously accepted and silently discarded.compute_sandwich_variance()computed its meat matrix asX' diag(e^4) Xinstead ofX' diag(e^2) X, giving standard errors about 3.5x too large. Both sandwich helpers are now checked againstsandwich::vcovHC().
Performance
- Voxelwise AR fitting no longer recomputes the run-level design projection for every voxel.
.fast_preproject()performs ann x nsolve and was being called once per voxel on a design that does not vary by voxel; hoisting it gives roughly a 1.7x speedup on the voxelwise AR path (4.95s to 2.98s for 2000 voxels at 300 timepoints).
Documentation
-
ar_voxelwisewas documented as overridingar_options$voxelwise. It never did — the options list took precedence — and disagreement is now an error. -
use_fast_pathwas documented as defaulting toFALSEin the runwise and chunkwise fitters; it defaults toTRUE. - Corrected claims that sandwich variance estimation is applied automatically. It is not used by any
fmri_lm()fitting path; the robust path reports a model-based weighted-least-squares variance. The accompanying degrees-of- freedom formula was also wrong and has been rewritten.
Changes
-
fmriARis now declared with a minimum version (>= 0.3.3) and listed inRemotes:; it previously had neither.
New Features
Reexported
feature()(from fmridesign) andfeature_regressor()(from fmrihrf) so mixed event formulas such asonset ~ hrf(condition) + feature(rms, dt = 0.1)work afterlibrary(fmrireg). Feature terms are sampled series, not trials; helpers that assumehrfspectrial structure skip or unwrap them instead of erroring (fitted_hrf(),shortnames(),design_plot(),preflight(), pair-contrast resolution).write_results()now exports statistical maps as NIfTI volumes viaformat = "nifti"(orformat = c("h5", "nifti")), reusing the same BIDS entity and filename machinery as the HDF5 backend. This removes the need to hand-roll loops overcoef_image()+neuroim2::write_vol().Added
coef_images(), a plural companion tocoef_image()that returns a named list ofNeuroVols for every coefficient of a giventype("estimates","contrasts", or"F") andstatistic.
Bug Fixes
-
write_results()now labels F-contrast maps asfstat/fpvalinstead of reusing thetstat/pvallabels. F statistics follow an F distribution (not Student’s t), so mixing them under atstatlabel produced mislabeled maps and, understrategy = "by_stat", could collide t- and F-contrast outputs in a single file. t- and F-contrasts are now written to separate, correctly labeled files.
fmrireg 0.1.2
Changes
- Moved PDF report generation (
report.fmri_lm) to the standalonefmrireportpackage. Usefmrireport::report()for report rendering.
Bug Fixes
- Fixed low-rank/sketch residual degrees of freedom to use original timepoints (
T - p) instead of sketch rows. - Replaced placeholder
fit_contrasts.fmri_lm()outputs with computed standard errors, test statistics, and p-values. - Consolidated duplicate meta-analysis pathways to shared implementations and removed inconsistent behavior across runwise/chunkwise pooling.
- Fixed F-contrast meta pooling to combine evidence via p-values rather than averaging F statistics.
- Fixed thread-safety issue in C++ meta kernels by deferring Paule-Mandel non-convergence warnings until after OpenMP regions.
- Added bounds validation and safer inverse fallback in sketch kernels to prevent unsafe indexing and hard failures on ill-conditioned data.
- Improved AR pipeline consistency for whitened covariance/fitted/residual handling and unified AR effective-df calculations.
- Added regression coverage for
fit_contrasts.fmri_lm()to prevent placeholder-stat regressions.
fmrireg 0.1.1
Bug Fixes
- Fixed
glm_lss()tests that incorrectly expected specific Cholesky decomposition errors. - Fixed convolution test with non-strictly-increasing onsets within blocks.
- Fixed testthat API usage (
expect_lt/expect_gtno longer use deprecatedinfoargument). - Fixed
latent_datasetAPI usage: now usesget_latent_scores()instead of deprecatedget_data(). - Changed
glm_lss()use_cppparameter default fromTRUEtoFALSE(C++ implementation retired; fmrilss package now used). - Added
fmrireg.suppress_deprecationoption check to all deprecated functions for cleaner test output. - Added
tests/testthat/setup.Rto suppress expected deprecation warnings during testing. - Suppressed expected kmeans convergence warnings in landmark SRHT tests.
fmrireg 0.1.0
Breaking Changes
-
Design Matrix Column Naming: The naming scheme for columns in design matrices generated by
event_model()has been completely revised for consistency and clarity.- All column names now strictly follow the format:
term_tag+_+condition_tag+ [_b##basis suffix]. -
term_tag: Automatically generated from variable names (e.g.,var1_var2) or user-providedid=inhrf(), sanitized (dots become underscores), and made unique with#suffix if needed (e.g.,cond,cond#1). -
condition_tag: Represents factor levels (e.g.,Factor.Level), continuous basis columns (e.g.,poly_RT_01,z_RT), or interactions joined by_(e.g.,Factor.Level_poly_RT_01). -
_b##: Optional suffix added only when the HRF has multiple basis functions (e.g.,_b01,_b02). - The previous
styleargument ("compact","qualified","uid") indesign_matrix()is removed. Only the single canonical format is produced. - Scripts or analyses that relied on matching previous column name formats (e.g., using
Var[Level],Var:Level,:basis[]) will need to be updated to use the newterm_tag_Condition.Tag_b##format.
- All column names now strictly follow the format:
Major Changes
-
Regressor System Refactoring:
- Introduced a new internal S3 class
Regfor representing regressors. - The main
regressor()function now usesReginternally but maintains backward compatibility (returns classc("regressor", "Reg", "list")). - Deprecated
single_trial_regressor()andnull_regressor()in favour of usingregressor()directly. - Unified regressor evaluation under the
evaluate.RegS3 method, supporting different calculation methods (“fft”, “conv”, “loop”, “Rconv”). - Evaluation methods now consistently use the refactored
evaluate.HRFfor HRF sampling. - Refactored C++ evaluation code into a single wrapper (
evaluate_regressor_cpp). - Removed redundant internal helper functions (
fastevalreg,fastevalreg2,conform_len,dots). - Implemented
autoplot.Reg(ggplot2) andprint.Reg(cli) methods, deprecating olderplot.regressorandprint.regressor. - Improved input validation and recycling for
regressor()arguments usingvctrs. - Added optional sparse matrix output to
evaluate.Reg. - Added memoization for HRF sampling within evaluation.
- Introduced a new internal S3 class