--- title: "Customising brain atlases" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Customising brain atlases} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r} #| label: setup-opts #| include: false knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ```{r} #| label: setup library(ggseg.formats) ``` Say you are preparing a figure that focuses on the subcortical structures visible in a single sagittal slice. You want to drop the views you don't need, remove small polygon fragments that clutter the image, turn some regions into non-legend context, and add a metadata column so you can facet by structure type. Every one of those steps is a single function call, and they all pipe together. ## The manipulation toolkit ggseg.formats provides three groups of manipulation functions. **Region functions** (`atlas_region_*`) control which regions are active in the atlas. **View functions** (`atlas_view_*`) control the 2D sf geometry—which views are present and how they are arranged. **Core functions** (`atlas_core_*`) enrich the region metadata. All of them accept a `ggseg_atlas` as the first argument, return a new `ggseg_atlas`, and play nicely with the pipe. ## Keeping and removing regions `atlas_region_remove()` strips a region entirely—from core, palette, sf geometry, and 3D data. The `pattern` argument is passed to `grepl()` with `ignore.case = TRUE`, so partial matches work: ```{r} #| label: region-remove no_cc <- atlas_region_remove(dk(), "corpus callosum") "corpus callosum" %in% atlas_regions(no_cc) ``` `atlas_region_keep()` is the inverse: it keeps only the regions that match and turns everything else into context geometry (sf is preserved for surface continuity, but non-matching regions leave core and palette): ```{r} #| label: region-keep frontal <- atlas_region_keep(dk(), "frontal") atlas_regions(frontal) ``` Both functions accept a `match_on` argument to choose whether the pattern matches against `"region"` (the default, human-readable name) or `"label"` (the unique identifier): ```{r} #| label: region-keep-label lh_only <- atlas_region_keep(dk(), "^lh_", match_on = "label") head(atlas_labels(lh_only)) ``` ## Context regions Sometimes you want a region's polygon to stay visible (rendered in grey) but not appear in the legend or carry data. This is what `atlas_region_contextual()` does. It removes the region from core, palette, and 3D data but leaves the sf geometry in place: ```{r} #| label: region-contextual ctx <- atlas_region_contextual(aseg(), "ventricle") "lateral ventricle" %in% atlas_regions(ctx) ``` Compare that to `atlas_region_remove()`, which would delete the ventricle polygons entirely, leaving gaps in the 2D slices. ## Renaming regions `atlas_region_rename()` changes the `region` column without touching `label` (so geometry links stay intact). Pass a fixed string: ```{r} #| label: region-rename renamed <- atlas_region_rename( dk(), "banks of superior temporal sulcus", "STS banks" ) "STS banks" %in% atlas_regions(renamed) ``` Or pass a function for programmatic renaming: ```{r} #| label: region-rename-func upper <- atlas_region_rename(dk(), ".*", toupper) head(atlas_regions(upper)) ``` ## Managing views `atlas_views()` tells you what 2D views an atlas has: ```{r} #| label: atlas-views atlas_views(aseg()) ``` `atlas_view_keep()` and `atlas_view_remove()` filter views by pattern. If you only want the sagittal slice: ```{r} #| label: view-keep sag <- atlas_view_keep(aseg(), "sagittal") atlas_views(sag) ``` Or remove several views at once by passing a vector: ```{r} #| label: view-remove fewer <- atlas_view_remove(aseg(), c("axial_3", "coronal_2")) atlas_views(fewer) ``` ## Cleaning up geometry After filtering regions you may have small polygon fragments left over—tiny slivers where a region just barely crossed a slice plane. `atlas_view_remove_small()` removes region polygons below a minimum area threshold. Context polygons (those not in core) are never removed: ```{r} #| label: view-remove-small cleaned <- atlas_view_remove_small(aseg(), min_area = 50) ``` You can scope the removal to specific views: ```{r} #| label: view-remove-small-scoped cleaned_sag <- atlas_view_remove_small( aseg(), min_area = 50, views = "sagittal" ) ``` `atlas_view_remove_region()` removes a specific region's sf geometry without touching core, palette, or 3D data. This is useful when a region's 2D projection is misleading but you still want it in 3D: ```{r} #| label: view-remove-region no_stem_sf <- atlas_view_remove_region( aseg(), "brain stem", match_on = "region" ) ``` ## Reordering and gathering When you remove views, the remaining geometry keeps its original coordinates, which can leave awkward gaps. `atlas_view_gather()` repositions views side-by-side with a configurable gap: ```{r} #| label: view-gather trimmed <- aseg() |> atlas_view_keep(c("sagittal", "coronal_3", "axial_3")) |> atlas_view_gather() atlas_views(trimmed) ``` `atlas_view_reorder()` lets you choose the left-to-right order and repositions at the same time. Views not mentioned in `order` are appended at the end: ```{r} #| label: view-reorder reordered <- aseg() |> atlas_view_keep(c("sagittal", "coronal_3", "axial_3")) |> atlas_view_reorder(c("axial_3", "sagittal", "coronal_3")) atlas_views(reordered) ``` ## Adding metadata `atlas_core_add()` left-joins a data frame onto the core table. This is useful for attaching grouping variables, statistical results, or any other per-region information. Here we add a custom network column to a handful of regions: ```{r} #| label: core-add network_info <- data.frame( region = c( "superior frontal", "precuneus", "inferior parietal", "posterior cingulate" ), network = "default mode" ) enriched <- atlas_core_add(dk(), network_info) enriched$core[!is.na(enriched$core$network), c("region", "network")] ``` The `by` argument defaults to `"region"` but you can join on any shared column. ## A full pipeline Here is a realistic pipeline that prepares the `aseg` atlas for a compact two-view figure of deep grey matter structures: ```{r} #| label: full-pipeline publication_aseg <- aseg() |> atlas_view_keep(c("sagittal", "coronal_3")) |> atlas_region_contextual("ventricle|choroid|white|cc") |> atlas_view_remove_small(min_area = 30) |> atlas_view_gather(gap = 0.1) publication_aseg ``` Each function returns a valid `ggseg_atlas`, so you can inspect intermediate results, branch the pipeline, or hand the final object straight to ggseg for plotting.