This vignette walks through task recipes that combine several xnatR functions. Each section is self-contained — jump to the one that matches your problem.
library(xnatR)
client <- xnat_connect(
base_url = "https://central.xnat.org",
username = "myuser",
password = "mypass",
use_jsession = TRUE
)You have a project ID and want to grab the newest data.
# Get the 20 most recent sessions, newest first
recent <- list_recent_sessions("MY_PROJECT", n = 20, client = client)
recentPick the first three unique subjects and download each one:
subjects <- unique(recent$subject_ID)[1:3]
subjects
#> [1] "SUBJ_042" "SUBJ_017" "SUBJ_099"
for (subj in subjects) {
download_subject(
project_id = "MY_PROJECT",
subject_id = subj,
dest_dir = "~/Downloads",
format = "zip",
client = client
)
}
#> ℹ Downloading 2 experiments for subject "SUBJ_042"
#> ✔ Downloaded all data for subject "SUBJ_042"
#> ℹ Downloading 1 experiment for subject "SUBJ_017"
#> ✔ Downloaded all data for subject "SUBJ_017"
#> ℹ Downloading 3 experiments for subject "SUBJ_099"
#> ✔ Downloaded all data for subject "SUBJ_099"If you want one zip per session instead of per subject, use
download_experiment():
The search builder lets you query across the entire XNAT instance. Here we find all MR sessions in a project acquired after a cutoff date:
sessions_2024 <- xnat_search_builder("xnat:mrSessionData") |>
search_select(
"xnat:mrSessionData/ID",
"xnat:mrSessionData/label",
"xnat:mrSessionData/subject_ID",
"xnat:mrSessionData/date"
) |>
search_where("xnat:mrSessionData/project", "EQUALS", "MY_PROJECT") |>
search_where("xnat:mrSessionData/date", "GREATER_THAN", "2024-01-01") |>
search_execute(client = client)
sessions_2024You can add more search_where() clauses — they combine
with AND logic. Use
list_queryable_fields("xnat:mrSessionData") to discover
what fields are available.
Need all T1-weighted scans with a specific TR?
search_scans() wraps the XML search API with a tidy
interface:
t1_scans <- search_scans(
project_id = "MY_PROJECT",
scan_type = "T1",
tr = 2300,
client = client
)
t1_scans
#> # A tibble: 12 × 8
#> subject_ID Project experiment_ID Type TR TE Flip Orientation
#> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <chr>
#> 1 SUBJ_001 MY_PROJECT E00042 T1 2300 2.98 9 Sagittal
#> 2 SUBJ_002 MY_PROJECT E00087 T1 2300 2.98 9 Sagittal
#> …The result includes the experiment ID, so you can pipe straight into a download:
Sometimes you want to see exactly what files exist before committing to a large download.
# What resources does this scan have?
resources <- list_resources(
project_id = "MY_PROJECT",
subject_id = "SUBJ_001",
experiment_id = "E00042",
scan_id = "1",
client = client
)
resources
#> ── XNAT Resources ─────────────────────────────
#> 3 resources
#> # A tibble: 3 × 3
#> label file_count file_size
#> <chr> <chr> <chr>
#> 1 DICOM 176 89.2 MB
#> 2 NIFTI 2 45.1 MB
#> 3 SNAPSHOTS 1 0.3 MB
# List individual files in the NIFTI resource
nifti_files <- list_files(
project_id = "MY_PROJECT",
subject_id = "SUBJ_001",
experiment_id = "E00042",
scan_id = "1",
resource = "NIFTI",
client = client
)
nifti_filesThen download just the resource you need:
For analysis planning, it helps to have a flat table of every scan in
a project. Combine list_experiments() and
list_scans():
# All sessions in the project
sessions <- list_experiments("MY_PROJECT", client = client)
# Collect scans for each session
scan_list <- lapply(seq_len(nrow(sessions)), function(i) {
scans <- list_scans(
project_id = sessions$project[i],
subject_id = sessions$subject_ID[i],
experiment_id = sessions$ID[i],
client = client
)
scans$experiment_id <- sessions$ID[i]
scans$subject_id <- sessions$subject_ID[i]
scans$session_date <- sessions$date[i]
scans
})
inventory <- do.call(rbind, scan_list)
inventoryNow you can filter with standard R: