--- title: Introduction to fmridesign description: Quick tour of the core workflow for building fMRI design matrices. output: rmarkdown::html_vignette: toc: yes toc_depth: 2 params: family: lapis preset: adobe base_size: 13 content_width: 80 vignette: | %\VignetteIndexEntry{Introduction to fmridesign} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} css: albers.css resource_files: - albers.css - albers.js includes: in_header: |- --- ```{r setup, include=FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.align = "center", fig.retina = 2, out.width = "100%", fig.width = 7, fig.asp = 0.618, message = FALSE, warning = FALSE ) set.seed(123) old_opts <- options(pillar.sigfig = 7, width = 80) old_theme <- ggplot2::theme_get() suppressPackageStartupMessages({ library(fmridesign) library(ggplot2) }) ggplot2::theme_set(ggplot2::theme_minimal(base_size = params$base_size)) ``` ```{r albers-family, echo=FALSE, results='asis'} cat(sprintf('', params$family)) ``` ```{r content-width, echo=FALSE, results='asis'} cat(sprintf('', params$content_width)) ``` ## Overview The `fmridesign` package constructs design matrices for fMRI general linear model (GLM) analysis. It provides a formula-based interface for specifying event-related designs with flexible hemodynamic response functions, parametric modulators, and baseline/nuisance regressors. The package separates task-related regressors (event models) from baseline regressors (drift, intercepts, motion), provides informative column names, and includes visualization tools for quality control. ## The fMRI Design Matrix In fMRI analysis, the design matrix (X) is fundamental to the general linear model: ```text Y = Xβ + ε ``` Where: - **Y**: Observed BOLD signal time series - **X**: Design matrix containing predictors - **β**: Parameter estimates (regression coefficients) - **ε**: Error term (noise) The design matrix typically combines task-related predictors (expected responses to events) and nuisance predictors (drift, motion, physiology). Both are essential for reliable inference. ## Package Architecture The package uses two main components: **Event models** (`event_model()`) specify task-related regressors. You provide onset times, event types, and optional durations. Each term can use a different HRF basis function. The model supports factorial designs, parametric modulators, and trial-specific covariates. **Baseline models** (`baseline_model()`) specify nuisance regressors. You can add polynomial or spline drift terms, block-wise intercepts, and any additional nuisance regressors (motion, physiological noise, etc.). ## Quick Start: Complete Workflow Here's a minimal example demonstrating the complete workflow from experimental design to design matrix: ```{r complete_example, fig.alt="Predicted BOLD regressors over time for an example event model (two runs)."} # 1. Define the temporal structure (2 runs, 150 scans each, TR = 2s) TR <- 2 sframe <- sampling_frame(blocklens = c(150, 150), TR = TR) # 2. Create experimental events set.seed(123) # Simple two-condition design with 20 events per run conditions <- rep(c("A", "B"), each = 10, times = 2) onsets <- c( sort(runif(20, 0, 150 * TR - 10)), # Run 1 sort(runif(20, 0, 150 * TR - 10)) # Run 2 ) blockids <- rep(1:2, each = 20) # 3. Build the event model emodel <- event_model( onset ~ hrf(Condition, basis = "spmg1"), data = data.frame( onset = onsets, Condition = factor(conditions), block = factor(blockids) ), block = ~ block, sampling_frame = sframe ) # 4. Build the baseline model bmodel <- baseline_model( basis = "poly", degree = 3, sframe = sframe ) # 5. Extract design matrices X_task <- design_matrix(emodel) X_baseline <- design_matrix(bmodel) # 6. Combine into full design matrix X_full <- cbind(X_task, X_baseline) dim(X_full) # 7. Visualize the complete design plot(emodel) ``` ## Understanding the Components ### Sampling Frame The `sampling_frame` object defines the temporal structure of your fMRI data: ```{r sampling_frame} # Single run: 200 scans, TR = 2 seconds sframe_single <- sampling_frame(blocklens = 200, TR = 2) print(sframe_single) # Multiple runs: 3 runs with different lengths sframe_multi <- sampling_frame(blocklens = c(150, 200, 150), TR = 2) print(sframe_multi) ``` ### Event Specification Events are typically specified with the formula interface: ```{r event_specification} # Formula interface (recommended) emodel_formula <- event_model( onset ~ hrf(condition) + hrf(RT, basis = "gaussian"), data = data.frame( onset = c(10, 30, 50, 70), condition = factor(c("easy", "hard", "easy", "hard")), RT = c(0.5, 0.8, 0.4, 0.9), block = factor(c(1, 1, 1, 1)) ), block = ~ block, sampling_frame = sampling_frame(100, TR = 2) ) ``` ## Common Use Cases ### 1. Block Design ```{r block_design, fig.alt="Block design regressors (task and rest blocks) over time."} # Block design with 20-second blocks block_onsets <- seq(0, 280, by = 40) block_conditions <- rep(c("task", "rest"), length.out = length(block_onsets)) block_durations <- rep(20, length(block_onsets)) emodel_block <- event_model( onset ~ hrf(condition), data = data.frame( onset = block_onsets, condition = factor(block_conditions), block = factor(rep(1, length(block_onsets))) ), block = ~ block, durations = block_durations, sampling_frame = sampling_frame(150, TR = 2) ) plot(emodel_block) ``` ### 2. Rapid Event-Related Design ```{r rapid_event} # Rapid event-related with jittered ISI set.seed(456) n_events <- 60 rapid_onsets <- cumsum(runif(n_events, 2, 6)) # ISI between 2-6s rapid_conditions <- sample(c("face", "house", "object"), n_events, replace = TRUE) emodel_rapid <- event_model( onset ~ hrf(stimulus), data = data.frame( onset = rapid_onsets, stimulus = factor(rapid_conditions), block = factor(rep(1, n_events)) ), block = ~ block, sampling_frame = sampling_frame(ceiling(max(rapid_onsets)/2) + 20, TR = 2) ) # Check design efficiency cor(design_matrix(emodel_rapid)) ``` ### 3. Parametric Modulation ```{r parametric, fig.alt="Parametric modulator (RT) regressor and conditions plotted over time."} # Event-related design with RT modulation set.seed(789) n_trials <- 30 pm_onsets <- sort(runif(n_trials, 0, 200)) pm_conditions <- rep(c("congruent", "incongruent"), length.out = n_trials) pm_RT <- rnorm(n_trials, mean = ifelse(pm_conditions == "congruent", 0.5, 0.7), sd = 0.1) emodel_parametric <- event_model( onset ~ hrf(condition) + hrf(RT), data = data.frame( onset = pm_onsets, condition = factor(pm_conditions), RT = scale(pm_RT)[,1], # Center the parametric modulator block = factor(rep(1, n_trials)) ), block = ~ block, sampling_frame = sampling_frame(120, TR = 2) ) # Visualize the parametric modulator plot(emodel_parametric, term_name = "RT") ``` ## Integration with fMRI Analysis The design matrices created by `fmridesign` can be used with various fMRI analysis approaches: ```{r integration, eval=FALSE} # Example: Export for use with external software X <- cbind(design_matrix(emodel), design_matrix(bmodel)) # Save as text file for SPM, FSL, or AFNI write.table(X, "design_matrix.txt", row.names = FALSE, col.names = TRUE) # For use with R-based analysis # Assuming Y is your fMRI time series data # fit <- lm(Y ~ X - 1) # -1 removes intercept as it's in the design # Or use with specialized fMRI packages # library(fmri) # results <- fmri_glm(Y, X) ``` ## Best Practices **Inspect your design matrices visually.** Check that event timing is correct, HRF shapes are reasonable, and correlations between regressors are acceptable. **Optimize design efficiency.** Use jittered inter-stimulus intervals and balanced event types when possible. **Match drift models to run length.** Short runs (< 5 minutes) need fewer drift terms than long runs. **Include nuisance regressors.** Add motion parameters, physiological noise, and artifact flags to your baseline model. ## Next Steps For more detailed information, see the following vignettes: - `vignette("a_03_baseline_model")`: In-depth coverage of baseline and nuisance modeling - `vignette("a_04_event_models")`: Comprehensive guide to event model specification - Visit the [fmrihrf package documentation](https://github.com/bbuchsbaum/fmrihrf) for HRF details ## Getting Help If you encounter issues or have questions: 1. Check the function documentation: `?event_model`, `?baseline_model` 2. Browse all available HRFs: `list_available_hrfs()` 3. Report issues: [GitHub Issues](https://github.com/bbuchsbaum/fmridesign/issues) ```{r cleanup, include=FALSE} options(old_opts) ggplot2::theme_set(old_theme) ```