Skip to contents

Introduction

This vignette demonstrates an end-to-end neuroimaging workflow in R by combining two packages:

  • openneuroR: fetches BIDS datasets from OpenNeuro
  • niflowr: processes neuroimaging data with FSL, AFNI, ANTs, and other tools

Together, they provide a reproducible pipeline from data acquisition to analysis, entirely within R.

Setup

Install both packages from GitHub:

# install.packages("pak")
pak::pak("bbuchsbaum/openneuroR")
pak::pak("bbuchsbaum/niflowr")

library(openneuroR)
library(niflowr)

Step 1: Browse OpenNeuro

Use on_search() to find datasets by keyword, then on_dataset() to view metadata:

# Search for flanker task datasets
results <- on_search("flanker")

# View details for ds000102 (flanker task)
dataset <- on_dataset("ds000102")
dataset$description

Step 2: Download with ni_from_openneuro()

The convenience function ni_from_openneuro() downloads a dataset and returns a BIDS object:

# Download first 3 subjects
bids <- ni_from_openneuro("ds000102", subjects = c("01", "02", "03"))

# Inspect the BIDS structure
print(bids)

This downloads to ~/openneuro_data/ds000102/ by default. Specify target_dir to customize.

Step 3: Process with niflowr

Skull strip T1w images

Use ni_bids_inputs() to find files matching a specific modality, then process them:

# Find T1w images for subject 01
inputs <- ni_bids_inputs(bids, "fsl.bet", subid = "01", modality = "T1w")

# Skull strip with FSL BET
result <- ni_fsl_bet(
  in_file = inputs$path[1],
  out_file = ni_deriv_path(inputs$path[1], desc = "brain"),
  frac = 0.5
)

Register to MNI space

Chain operations by using output from one step as input to the next:

# Register brain-extracted T1w to MNI152
reg_result <- ni_fsl_flirt(
  in_file = result$out_file,
  ref_file = ni_fsl_template("MNI152_T1_2mm_brain"),
  out_file = ni_deriv_path(result$out_file, space = "MNI152"),
  out_matrix_file = ni_deriv_path(result$out_file, suffix = "xfm", ext = "mat")
)

Step 4: Scale with targets

Use targets to process multiple subjects in parallel:

library(targets)

# _targets.R
tar_option_set(packages = c("niflowr", "openneuroR"))

list(
  tar_target(bids, ni_from_openneuro("ds000102", subjects = c("01", "02", "03"))),

  tar_target(
    subjects,
    bids$participants$participant_id
  ),

  tar_target(
    brain_extracted,
    {
      inputs <- ni_bids_inputs(bids, "fsl.bet", subid = subjects, modality = "T1w")
      ni_fsl_bet(
        in_file = inputs$path[1],
        out_file = ni_deriv_path(inputs$path[1], desc = "brain"),
        frac = 0.5
      )
    },
    pattern = map(subjects)
  ),

  tar_target(
    registered,
    {
      ni_fsl_flirt(
        in_file = brain_extracted$out_file,
        ref_file = ni_fsl_template("MNI152_T1_2mm_brain"),
        out_file = ni_deriv_path(brain_extracted$out_file, space = "MNI152")
      )
    },
    pattern = map(brain_extracted)
  )
)

Run with targets::tar_make().

Working with fMRIPrep derivatives

If the dataset has preprocessed derivatives on OpenNeuro, download and use them directly:

# Download fMRIPrep derivatives
on_download_derivatives(
  dataset = "ds000102",
  derivative = "fmriprep",
  dest_dir = "~/openneuro_data/ds000102/derivatives",
  subjects = c("01", "02")
)

# Load confounds
confounds <- ni_fmriprep_confounds(
  "~/openneuro_data/ds000102/derivatives/fmriprep/sub-01/func/sub-01_task-flanker_desc-confounds_timeseries.tsv"
)

# Load preprocessed BOLD
preproc <- ni_fmriprep_preproc(
  "~/openneuro_data/ds000102/derivatives/fmriprep/sub-01/func/sub-01_task-flanker_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz"
)

Tips

Caching: OpenNeuro downloads are cached. Re-running ni_from_openneuro() with the same arguments will reuse existing files.

Offline work: Once downloaded, all processing happens locally. Disconnect and continue working.

Reproducibility: Use renv::snapshot() to lock package versions and ensure reproducible results across environments.

Container profiles: Use ni_set_runtime_profile() to switch between Docker, Apptainer, or native execution. See vignette("container-profiles") for details.

Next steps

  • Explore wrapper functions with ni_list_wrappers()
  • Build complex pipelines with ni_pipe()
  • Read vignette("niflowr-basics") for more processing examples