The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.

Customising brain atlases

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:

no_cc <- atlas_region_remove(dk(), "corpus callosum")
"corpus callosum" %in% atlas_regions(no_cc)
#> [1] FALSE

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):

frontal <- atlas_region_keep(dk(), "frontal")
atlas_regions(frontal)
#> [1] "caudal middle frontal"  "frontal pole"           "lateral orbitofrontal" 
#> [4] "medial orbitofrontal"   "rostral middle frontal" "superior 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):

lh_only <- atlas_region_keep(dk(), "^lh_", match_on = "label")
head(atlas_labels(lh_only))
#> [1] "lh_bankssts"                "lh_caudalanteriorcingulate"
#> [3] "lh_caudalmiddlefrontal"     "lh_corpuscallosum"         
#> [5] "lh_cuneus"                  "lh_entorhinal"

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:

ctx <- atlas_region_contextual(aseg(), "ventricle")
"lateral ventricle" %in% atlas_regions(ctx)
#> [1] FALSE

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:

renamed <- atlas_region_rename(
  dk(),
  "banks of superior temporal sulcus",
  "STS banks"
)
"STS banks" %in% atlas_regions(renamed)
#> [1] TRUE

Or pass a function for programmatic renaming:

upper <- atlas_region_rename(dk(), ".*", toupper)
head(atlas_regions(upper))
#> [1] "BANKS OF SUPERIOR TEMPORAL SULCUS" "CAUDAL ANTERIOR CINGULATE"        
#> [3] "CAUDAL MIDDLE FRONTAL"             "CORPUS CALLOSUM"                  
#> [5] "CUNEUS"                            "ENTORHINAL"

Managing views

atlas_views() tells you what 2D views an atlas has:

atlas_views(aseg())
#> [1] "axial_3"   "axial_4"   "axial_5"   "axial_6"   "coronal_1" "coronal_2"
#> [7] "sagittal"

atlas_view_keep() and atlas_view_remove() filter views by pattern. If you only want the sagittal slice:

sag <- atlas_view_keep(aseg(), "sagittal")
atlas_views(sag)
#> [1] "sagittal"

Or remove several views at once by passing a vector:

fewer <- atlas_view_remove(aseg(), c("axial_3", "coronal_2"))
atlas_views(fewer)
#> [1] "axial_4"   "axial_5"   "axial_6"   "coronal_1" "sagittal"

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:

cleaned <- atlas_view_remove_small(aseg(), min_area = 50)
#> ℹ Removed 20 geometries below area 50

You can scope the removal to specific views:

cleaned_sag <- atlas_view_remove_small(
  aseg(),
  min_area = 50,
  views = "sagittal"
)
#> ℹ Removed 2 geometries below area 50

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:

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:

trimmed <- aseg() |>
  atlas_view_keep(c("sagittal", "coronal_3", "axial_3")) |>
  atlas_view_gather()
atlas_views(trimmed)
#> [1] "axial_3"  "sagittal"

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:

reordered <- aseg() |>
  atlas_view_keep(c("sagittal", "coronal_3", "axial_3")) |>
  atlas_view_reorder(c("axial_3", "sagittal", "coronal_3"))
atlas_views(reordered)
#> [1] "axial_3"  "sagittal"

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:

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")]
#> # A tibble: 8 × 2
#>   region              network     
#>   <chr>               <chr>       
#> 1 inferior parietal   default mode
#> 2 posterior cingulate default mode
#> 3 precuneus           default mode
#> 4 superior frontal    default mode
#> 5 inferior parietal   default mode
#> 6 posterior cingulate default mode
#> 7 precuneus           default mode
#> 8 superior frontal    default mode

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:

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)
#> ℹ Removed 2 geometries below area 30

publication_aseg
#> 
#> ── aseg ggseg atlas ────────────────────────────────────────────────────────────
#> Type: subcortical
#> Regions: 12
#> Hemispheres: left, NA, right
#> Views: sagittal
#> Palette: ✔
#> Rendering: ✔ ggseg
#> ✔ ggseg3d (meshes)
#> ────────────────────────────────────────────────────────────────────────────────
#> # A tibble: 38 × 4
#>    hemi  region          label                   structure    
#>    <chr> <chr>           <chr>                   <chr>        
#>  1 left  Cerebellum      Left-Cerebellum-Cortex  cerebellum   
#>  2 left  Cerebellum      Left-Cerebellum-Cortex  cerebellum   
#>  3 left  Thalamus        Left-Thalamus           basal ganglia
#>  4 left  Thalamus        Left-Thalamus           basal ganglia
#>  5 left  Thalamus Proper Left-Thalamus           basal ganglia
#>  6 left  Thalamus Proper Left-Thalamus           basal ganglia
#>  7 left  Caudate         Left-Caudate            basal ganglia
#>  8 left  Caudate         Left-Caudate            basal ganglia
#>  9 left  Putamen         Left-Putamen            basal ganglia
#> 10 left  Putamen         Left-Putamen            basal ganglia
#> 11 left  Pallidum        Left-Pallidum           basal ganglia
#> 12 left  Pallidum        Left-Pallidum           basal ganglia
#> 13 <NA>  Brain Stem      Brain-Stem              brainstem    
#> 14 left  Hippocampus     Left-Hippocampus        limbic       
#> 15 left  Hippocampus     Left-Hippocampus        limbic       
#> 16 left  Amygdala        Left-Amygdala           limbic       
#> 17 left  Amygdala        Left-Amygdala           limbic       
#> 18 left  ventraldc       Left-VentralDC          <NA>         
#> 19 left  vessel          Left-vessel             <NA>         
#> 20 right Cerebellum      Right-Cerebellum-Cortex cerebellum   
#> 21 right Cerebellum      Right-Cerebellum-Cortex cerebellum   
#> 22 right Thalamus        Right-Thalamus          basal ganglia
#> 23 right Thalamus        Right-Thalamus          basal ganglia
#> 24 right Thalamus Proper Right-Thalamus          basal ganglia
#> 25 right Thalamus Proper Right-Thalamus          basal ganglia
#> 26 right Caudate         Right-Caudate           basal ganglia
#> 27 right Caudate         Right-Caudate           basal ganglia
#> 28 right Putamen         Right-Putamen           basal ganglia
#> 29 right Putamen         Right-Putamen           basal ganglia
#> 30 right Pallidum        Right-Pallidum          basal ganglia
#> 31 right Pallidum        Right-Pallidum          basal ganglia
#> 32 right Hippocampus     Right-Hippocampus       limbic       
#> 33 right Hippocampus     Right-Hippocampus       limbic       
#> 34 right Amygdala        Right-Amygdala          limbic       
#> 35 right Amygdala        Right-Amygdala          limbic       
#> 36 right ventraldc       Right-VentralDC         <NA>         
#> 37 right vessel          Right-vessel            <NA>         
#> 38 <NA>  Optic Chiasm    Optic-Chiasm            other

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.

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.