Slice visualization with neuroim2

You often need to answer a simple question before doing anything more complicated with a brain image: does this volume look plausible, and does the map or registration result line up with it?

The plotting helpers in neuroim2 are meant for that first visual check. They work with NeuroVol objects, preserve image aspect ratio, use robust intensity scaling by default, and return ordinary ggplot2 objects or lists of panels when you want to customize or save the result.

What are we plotting?

This vignette uses a small anatomical image shipped with the package. We also build a synthetic signed statistical map and simple anatomical edge masks on the same NeuroSpace grid so the overlay and registration-QC examples are reproducible.

anat_path <- system.file("extdata", "mni_downsampled.nii.gz", package = "neuroim2")
raw_anat <- read_vol(anat_path)

data.frame(
  object = "raw_anat",
  class = class(raw_anat)[1],
  dimensions = paste(dim(raw_anat), collapse = " x ")
)
#>     object         class   dimensions
#> 1 raw_anat DenseNeuroVol 48 x 57 x 48

How do I make a slice montage?

Use plot_montage() when you want to scan several slices at once. The function returns a single ggplot2 object, so you can print it, add labels, or save it with your usual plotting workflow.

plot_montage(
  anat,
  zlevels = zlevels,
  ncol = 6,
  cmap = anatomy_cmap,
  range = "robust",
  title = "Anatomical montage",
  style = "dark"
)
Six axial anatomical slices on a dark background.

A dark-style anatomical montage with robust intensity scaling.

Use the light style when you are preparing a figure for a manuscript page or a white-background report.

plot_montage(
  anat,
  zlevels = zlevels[1:4],
  ncol = 4,
  cmap = anatomy_cmap,
  range = "robust",
  title = "Light style montage",
  style = "light"
)
Six axial anatomical slices on a light background.

The same slices using the light plotting style.

How do I inspect one location in three planes?

Use plot_ortho() when you care about one voxel or world coordinate. The default crosshairs make it easier to confirm that the same location is shown in the axial, coronal, and sagittal panels.

plot_ortho(
  anat,
  coord = center_voxel,
  unit = "index",
  cmap = anatomy_cmap,
  title = "Three-plane view",
  style = "dark"
)
Axial, coronal, and sagittal slices with crosshairs.

Orthogonal view through the center voxel.

If you want the panels without drawing them immediately, set draw = FALSE. That is useful in scripts that save plots or compose figures later.

ortho_panels <- plot_ortho(anat, coord = center_voxel, draw = FALSE)
names(ortho_panels)
#> [1] "axial"    "coronal"  "sagittal"

How do I overlay a signed statistical map?

Use plot_overlay() when you have a background image and a second volume on the same grid. For signed maps, a diverging palette and symmetric overlay limits make positive and negative clusters comparable.

plot_overlay(
  bgvol = anat,
  overlay = stat_map,
  zlevels = zlevels,
  bg_cmap = anatomy_cmap,
  bg_range = "robust",
  ov_range = "robust",
  ov_thresh = 1.8,
  ov_alpha = 0.75,
  ov_cmap = "coldhot",
  ov_symmetric = TRUE,
  ncol = 6,
  title = "Thresholded signed overlay",
  style = "dark"
)
An anatomical montage with blue and orange statistical clusters.

Signed statistical map overlaid on the anatomical image.

data.frame(
  positive_voxels = sum(stat_arr > 1.8),
  negative_voxels = sum(stat_arr < -1.8),
  max_stat = round(max(stat_arr), 2),
  min_stat = round(min(stat_arr), 2)
)
#>   positive_voxels negative_voxels max_stat min_stat
#> 1             483             287     4.18    -3.59

How do I check registration by eye?

Registration QC usually asks whether two images or edge maps agree on the same grid. The QC helpers intentionally require matching NeuroSpace objects; if the grids differ, resample first rather than relying on a plot to hide the mismatch.

plot_checkerboard() alternates tiles from a reference and comparison volume. Misalignment shows up as broken anatomy across tile boundaries.

plot_checkerboard(
  anat,
  comparison,
  zlevels = zlevels,
  tile = 8,
  cmap = anatomy_cmap,
  ncol = 6,
  title = "Checkerboard registration QC",
  style = "dark"
)
Checkerboard slices showing discontinuities from a shifted comparison image.

Checkerboard comparison between the anatomical image and a shifted copy.

plot_edge_overlay() is useful when you have fixed and moving edge maps. Here the moving edge mask is shifted by three voxels, so the mismatch is visible where the colored edges separate.

plot_edge_overlay(
  anat,
  fixed_edges,
  moving_edges,
  zlevels = zlevels,
  bg_cmap = anatomy_cmap,
  ncol = 6,
  title = "Edge overlay registration QC",
  style = "dark"
)
Edge overlay QC slices with colored edge disagreement.

Fixed and moving edge maps overlaid on the anatomical image.

Which helper should I reach for?

Task Helper
Quick axial scan of one volume plot() or plot_montage()
Publication-style slice grid plot_montage()
One location in axial/coronal/sagittal planes plot_ortho()
Statistical or mask overlay on anatomy plot_overlay()
Registration check from two images plot_checkerboard()
Registration check from edge maps plot_edge_overlay()
Shared package styling theme_neuro()

Practical tips

  • Use range = "robust" for anatomical images unless outliers are the point.
  • Use ov_symmetric = TRUE with diverging palettes for signed overlays.
  • Use style = "dark" for visual inspection and style = "light" for reports that need a white page.
  • Use draw = FALSE when a helper returns multiple panels and you want to save or arrange them yourself.

For related workflows, see vignette("ImageVolumes") for volume objects, vignette("coordinate-systems") for voxel/world coordinates, and vignette("Resampling") before plotting images that do not already share a grid.