Skip to contents

[Experimental]

Turn a subcortical segmentation volume (like aseg.mgz) into a brain atlas with 3D meshes for each structure. The function extracts each labelled region from the volume, creates a surface mesh, and smooths it.

For 2D plotting, the function can also generate slice views by taking snapshots at specified coordinates and extracting contours.

Requires FreeSurfer for mesh generation.

Usage

create_subcortical_from_volume(
  input_volume,
  decimate = 0.5,
  verbose = get_verbose(),
  ...,
  input_lut = NULL,
  atlas_name = NULL,
  output_dir = NULL,
  slabs = NULL,
  vertex_size_limits = NULL,
  min_coverage = NULL,
  cleanup = NULL,
  skip_existing = NULL,
  steps = NULL
)

Arguments

input_volume

Path to the segmentation volume. Supports .mgz, .nii, and .nii.gz formats. Typically this is aseg.mgz or a custom segmentation in the same space. May also be the list(volume, lut, id_offset) returned by prepare_subcortical_anatomical() / project_volume_anatomical(), in which case its volume and lut are used (an explicit input_lut takes precedence over the bundled one).

decimate

Mesh decimation factor between 0 and 1. Reduces the number of faces in 3D meshes using quadric edge decimation (via Rvcg::vcgQEdecim()). A value of 0.5 reduces faces by 50%. Set to NULL to skip decimation. Requires the Rvcg package. Default is 0.5.

verbose

How much to print: 0 silent, 1 progress (the default), 2 adds FreeSurfer's own output. TRUE and FALSE mean 1 and 0. Falls back to options("ggseg.extra.verbose"), then GGSEG_EXTRA_VERBOSE.

...

Not used. Present so that a mistyped or misplaced argument is reported against this function rather than silently ignored; anything passed here is an error. Geometry is shaped after the build: see atlas_polish(), or atlas_simplify(), atlas_smooth() and atlas_dilate() individually.

input_lut

Path to a FreeSurfer-style colour lookup table that maps label IDs to region names and colours (e.g., FreeSurferColorLUT.txt or ASegStatsLUT.txt), or a data.frame with columns idx, label, R, G, B and A (see is_lut()).

The table decides what is a region and what is context, the grey anatomy the regions are drawn against. Nothing is recognised by its id or its name:

  • A row is a region unless it says otherwise. It gets a mesh, a colour and a shape in each 2D view.

  • A row whose optional context column is TRUE is context. It keeps its name, is traced on one slice per view rather than projected through the slab, and gets no mesh.

  • A label in the volume that the table does not list is context too. With no name to go by, it is called context_ and its id, such as context_0002.

To leave a context shape out of the atlas altogether, remove it afterwards with ggseg.formats::atlas_context_remove(). To treat the context differently when polishing, pass context_pattern as labels or exclude; see context_pattern().

Either form may also carry a hemi column ("left", "right" or "midline") that sets each region's hemisphere; a row left NA, or a table without the column, has it read from the label's name, and any other value is an error. write_lut() stores the column in a file.

A data.frame may also carry a names column: the display name each region shows in a legend. A row left NA, or a table without the column, is named after its region.

If NULL, every label is a region with a generic name (e.g., "region_0010"), there is no context, and the atlas will have no palette.

atlas_name

Name for the atlas. If NULL, derived from the input filename. It also names the folder of intermediate files inside output_dir, so it must be a single name without path separators.

output_dir

Where to put the intermediate files. Defaults to tempdir(), from options("ggseg.extra.output_dir") or GGSEG_EXTRA_OUTPUT_DIR.

slabs

A data.frame specifying projection slabs with columns name, type ("axial", "coronal", "sagittal"), start (first slice), end (last slice). Defaults to three coronal and three axial slabs tiling the bounding box of the atlas's own labels, plus one left-hemisphere sagittal slab, so the band follows the anatomy of the volume rather than a fixed set of slice indices. Unlike slices, projections show ALL structures in their spatial relationships - like an X-ray view. May also be a named list of subcortical_slabs() arguments (e.g. slabs = list(labels = 801:810, coronal = 3, axial = 2)); it is expanded into a slab table with volume defaulting to input_volume, so the slab indices are computed in the builder's own frame.

vertex_size_limits

Numeric vector of length 2 setting minimum and maximum vertex count for polygons. Polygons outside this range are filtered out. Default NULL applies no limits.

min_coverage

Smallest share of core labels that must end up with 2D geometry, between 0 and 1. A build that falls below it warns and names the labels that have no shape; the warning fires whatever verbose is set to, because a region that cannot be drawn is data loss rather than progress chatter. The build itself still returns, so a long pipeline is never thrown away over a threshold. Use 0 to turn the check off. Defaults to 0.8, or to options("ggseg.extra.min_coverage"), then GGSEG_EXTRA_MIN_COVERAGE.

cleanup

Remove the intermediate files afterwards. Default TRUE, from options("ggseg.extra.cleanup") or GGSEG_EXTRA_CLEANUP.

The intermediate files live in a folder named after the atlas inside output_dir, and the whole folder is removed. A build therefore refuses to start if that folder already holds files it did not write, since removing it would take them too. Choose another output_dir or atlas_name, or pass FALSE to build there and keep everything.

skip_existing

Reuse a step's intermediate files when they already exist, instead of running the step. Default FALSE, from options("ggseg.extra.skip_existing") or GGSEG_EXTRA_SKIP_EXISTING.

A cache records which ggseg.extra wrote it, not what it was built from, so reuse cannot tell that the volume or lookup table has changed. Reuse is therefore asked for rather than assumed, and is reported when it happens. To continue an interrupted build, either pass TRUE or leave the finished steps out of steps.

steps

Which pipeline steps to run. Default NULL runs all six:

  • 1: Extract labels from the volume and read the colour table

  • 2: Create a mesh for each structure

  • 3: Build atlas data (3D only if stopping here)

  • 4: Create projection snapshots

  • 5: Extract contours

  • 6: Build the final atlas with 2D geometry

Use steps = 1:3 for a 3D-only atlas. Geometry is shaped after the build, not during it: see atlas_polish().

Value

A ggseg_atlas object with region metadata (core), 3D meshes, a colour palette, and optionally sf geometry for 2D slice plots.

Examples

if (FALSE) { # \dontrun{
# Create 3D-only subcortical atlas from aseg
atlas <- create_subcortical_from_volume(
  input_volume = "path/to/aseg.mgz",
  input_lut = "path/to/FreeSurferColorLUT.txt",
  steps = 1:3
)

# View with ggseg3d
ggseg3d::ggseg3d(atlas = atlas)

# Full atlas with 2D slices
atlas <- create_subcortical_from_volume(
  input_volume = "path/to/aseg.mgz",
  input_lut = "path/to/ASegStatsLUT.txt"
)

# Post-process to remove/modify regions (functions from ggseg.formats)
atlas <- atlas |>
  atlas_region_remove("White-Matter", match_on = "label") |>
  atlas_region_contextual("Cortex", match_on = "label")
} # }