--- title: "Reading FreeSurfer stats files" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Reading FreeSurfer stats files} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r} #| label: setup #| include: false knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE ) ``` FreeSurfer's `recon-all` produces stats files with region-level measures -- cortical thickness, surface area, volume. ggseg includes readers that pull these files directly into data frames shaped for plotting. All three functions below come from the `ggseg.formats` package, which ggseg re-exports. ```{r} #| label: load-packages library(ggseg) library(ggplot2) library(dplyr) ``` ## Reading a single stats file After `recon-all` finishes, each subject has a `stats/` folder with parcellation data. `read_freesurfer_stats()` reads one file at a time: ```{r} #| label: read-single-stats subjects_dir <- Sys.getenv("SUBJECTS_DIR") stats_file <- file.path(subjects_dir, "bert/stats/lh.aparc.stats") data <- read_freesurfer_stats(stats_file) data ``` The hemisphere is encoded in the filename (`lh.` or `rh.`). To match the atlas, prepend it to the label column: ```{r} #| label: fig-single-stats #| fig-cap: "Brain plot of average cortical thickness from a single stats file." ggplot(data |> mutate(label = paste0("lh_", label))) + geom_brain(atlas = dk(), mapping = aes(fill = ThickAvg)) ``` ## Reading stats files across subjects `read_atlas_files()` reads all matching stats files from a subjects directory. Pass a regular expression to select the right files: ```{r} #| label: read-atlas-files dat <- read_atlas_files(subjects_dir, "aparc.stats$") dat ``` The trailing `$` matters -- it ensures you get `aparc.stats` but not `aparc.a2009s.stats`. The function adds hemisphere prefixes automatically, so the data is ready for plotting: ```{r} #| label: fig-atlas-files #| fig-cap: "Brain plot of cortical thickness variability across subjects." ggplot(dat) + geom_brain(atlas = dk(), mapping = aes(fill = ThickStd)) ``` To show all metrics at once, pivot and facet: ```{r} #| label: fig-all-metrics #| fig-cap: "All FreeSurfer metrics shown in faceted brain plots." #| fig-width: 10 library(tidyr) dat |> pivot_longer(-c(subject, label), names_to = "stat", values_to = "val") |> ggplot() + geom_brain(atlas = dk(), mapping = aes(fill = val)) + facet_wrap(~stat) ``` ## Reading FreeSurfer stats tables FreeSurfer's `aparcstats2table` and `asegstats2table` commands create summary tables across subjects. Read these with `read_freesurfer_table()`: ```{r} #| label: read-fs-table table_path <- "path/to/aparc.volume.table" read_freesurfer_table(table_path) ``` The output has three columns: subject, label, and value. ## Cleaning label suffixes Stats tables append the measure name to each label (e.g. `lh_bankssts_volume`). The `measure` argument strips that suffix and renames the value column: ```{r} #| label: read-fs-table-measure dat <- read_freesurfer_table(table_path, measure = "volume") dat ``` ## Filtering non-region rows FreeSurfer tables include summary measures (total volume, ICV) that don't correspond to atlas regions. Filter them before plotting: ```{r} #| label: fig-filtered-table #| fig-cap: "Brain plot of volume data after filtering non-region rows." ggplot(dat |> filter(grepl("lh|rh", label))) + geom_brain(atlas = dk(), mapping = aes(fill = volume)) ``` The `grepl("lh|rh", label)` pattern keeps only hemisphere-specific rows.