--- title: Create Mock BIDS Projects for Tests and Examples output: rmarkdown::html_vignette: toc: yes toc_depth: 2.0 css: albers.css header-includes: - '' params: family: red preset: homage resource_files: - albers.css - albers.js vignette: | %\VignetteIndexEntry{Create Mock BIDS Projects for Tests and Examples} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", message = FALSE, warning = FALSE ) ``` ```{r albers-classes, echo=FALSE, results='asis'} cat(sprintf( paste0( '' ), params$family, params$preset )) ``` ```{r theme-setup, include = FALSE} if (requireNamespace("ggplot2", quietly = TRUE) && requireNamespace("albersdown", quietly = TRUE)) { if (requireNamespace("ggplot2", quietly = TRUE) && requireNamespace("albersdown", quietly = TRUE)) ggplot2::theme_set(albersdown::theme_albers(family = params$family, preset = params$preset)) } suppressPackageStartupMessages({ library(bidser) library(dplyr) library(tidyr) library(tibble) }) ``` If you are writing tests, teaching examples, or demonstrating archive workflows, you usually do not want a downloaded dataset. You want a tiny BIDS project that lives on disk, has predictable contents, and can include both raw and derivative files. `create_mock_bids()` is the entry point for that job. ## What does a small mock project look like? Start by defining participants and a file inventory. ```{r define-layout} participants <- tibble( participant_id = c("01", "02") ) file_structure <- tribble( ~subid, ~datatype, ~task, ~run, ~suffix, ~fmriprep, "01", "func", "rest", "01", "bold.nii.gz", FALSE, "01", "func", "rest", "01", "events.tsv", FALSE, "01", "func", "rest", "01", "bold.nii.gz", TRUE, "01", "func", "rest", "01", "desc-confounds_timeseries.tsv", TRUE, "02", "func", "rest", "01", "bold.nii.gz", FALSE, "02", "func", "rest", "01", "events.tsv", FALSE ) ``` Now add the tabular payloads you want written into event and confound files. ```{r define-payloads} event_data <- list( "sub-01/func/sub-01_task-rest_run-01_events.tsv" = tibble( onset = c(0, 12), duration = c(1, 1), trial_type = c("cue", "target") ), "sub-02/func/sub-02_task-rest_run-01_events.tsv" = tibble( onset = c(0, 10), duration = c(1, 1), trial_type = c("cue", "target") ) ) confound_data <- list( "derivatives/mockprep/sub-01/func/sub-01_task-rest_run-01_desc-confounds_timeseries.tsv" = tibble( CSF = c(0.10, 0.20, 0.30, 0.20), WhiteMatter = c(0.30, 0.40, 0.50, 0.40), GlobalSignal = c(1.00, 1.10, 1.20, 1.10), FramewiseDisplacement = c(0.01, 0.02, 0.03, 0.02) ) ) ``` Create the project on disk so you can query it and archive it later. ```{r create-project} mock_dir <- tempfile("bidser-mock-") mock_proj <- create_mock_bids( project_name = "RestMock", participants = participants, file_structure = file_structure, event_data = event_data, confound_data = confound_data, create_stub = TRUE, stub_path = mock_dir, prep_dir = "derivatives/mockprep" ) mock_proj stopifnot(file.exists(file.path(mock_dir, "participants.tsv"))) ``` You can inspect the resulting layout immediately with `plot_bids()`. ```{r plot-project} plot_bids(mock_proj, interactive = FALSE) ``` ## How do you query raw and derivative files? Because `query_files()` works on mock projects too, you can test selection logic before you point the same code at a real dataset. ```{r query-scope} raw_runs <- query_files( mock_proj, regex = "bold\\.nii\\.gz$", scope = "raw", return = "tibble" ) derivative_runs <- query_files( mock_proj, regex = "bold\\.nii\\.gz$", scope = "derivatives", return = "tibble" ) raw_runs[, c("path", "scope")] derivative_runs[, c("path", "scope", "pipeline")] stopifnot( nrow(raw_runs) == 2L, nrow(derivative_runs) == 1L ) ``` ## How do you inspect injected events and confounds? The mock project stores real tabular data, so the higher-level readers work the same way they do on a real project. ```{r inspect-events} subject_events <- read_events(mock_proj, subid = "01") %>% unnest(cols = data) subject_events stopifnot( nrow(subject_events) == 2L, all(subject_events$duration > 0) ) ``` ```{r inspect-confounds} mock_confounds <- read_confounds( mock_proj, subid = "01", nest = FALSE ) mock_confounds stopifnot( nrow(mock_confounds) == 4L, all(is.finite(mock_confounds$GlobalSignal)), max(mock_confounds$FramewiseDisplacement) < 0.05 ) ``` That makes mock projects useful for both file-level tests and downstream table checks. ## How do you pack the project for sharing? `pack_bids()` creates an archive while replacing imaging files with zero-byte stubs. That keeps the layout and tabular metadata intact without shipping full images. ```{r pack-project} archive_file <- tempfile(fileext = ".tar.gz") packed <- pack_bids(mock_proj, output_file = archive_file, verbose = FALSE) archive_contents <- list_pack_bids(packed, verbose = FALSE) archive_contents %>% select(file, type, is_stub) %>% head() archive_contents %>% summarise( n_files = n(), n_stubs = sum(is_stub), n_tsv = sum(type == "tsv") ) stopifnot( file.exists(packed), any(archive_contents$is_stub) ) ``` ## Next Steps Use `vignette("quickstart")` for reader-facing BIDS discovery and `vignette("derivatives")` when you want to move from file inventories to pipeline-aware derivative summaries. ```{r cleanup, include = FALSE} if (exists("archive_file")) { unlink(archive_file, force = TRUE) } if (exists("mock_dir")) { unlink(mock_dir, recursive = TRUE, force = TRUE) } ```