vis.volume.clusters: Visualize clusters of a volume inside a translucent...

View source: R/vis_volume_clusters.R

vis.volume.clustersR Documentation

Visualize clusters of a volume inside a translucent anatomical mesh.

Description

Visualize the clusters of a volume, e.g., the supra-threshold voxels of a statistical map, as 3D iso-surfaces inside a single semi-transparent anatomical mesh (the context, typically the cortex of the same subject). A cluster is rendered as a set of nested iso-surface shells: the outermost shell is the iso-surface at the threshold (the cluster boundary), the inner ones sit at the higher iso-levels, and the innermost shell is at the cluster peak. This way the shape of the cluster and the location of its peak are visible at the same time, and the voxel structure of the data does not show up as staircase artifacts.

The shells are colored with a diverging colormap that encodes the iso-level, i.e., they use exactly the colors that the colorbar shows, and they become more opaque towards the core of the cluster, so that the core is visible through the outer shells. Positive and negative clusters can be rendered together, they use the two halves of the diverging colormap.

To render the clusters without a context mesh, pass context = NULL. To show the location of the clusters within a specific subject, use the context parameter to select the surface (e.g., "white" or "pial"); the surfaces of the fsaverage template subject can be downloaded with download_fsaverage if needed.

Usage

vis.volume.clusters(
  subjects_dir = NULL,
  subject_id = "fsaverage",
  volume,
  threshold = NULL,
  threshold_quantile = 0.95,
  max_level = NULL,
  max_level_quantile = 0.99,
  num_levels = 4L,
  positive = TRUE,
  negative = TRUE,
  smoothing = 2L,
  downsample = 1L,
  frame = 1L,
  backend = "auto",
  context = list(surface = "white", alpha = 0.05),
  alpha_range = c(0.08, 1),
  makecmap_options = mkco.cluster(),
  views = c("sd_lateral_lh", "sd_medial_lh", "sd_lateral_rh", "sd_medial_rh"),
  rgloptions = rglo(),
  rglactions = list(),
  silent = FALSE
)

Arguments

subjects_dir

string or NULL. The FreeSurfer SUBJECTS_DIR, i.e., a directory containing the data for all your subjects, each in a subdir named after the subject identifier. If NULL (the default), the subject directory is searched in the package cache, SUBJECTS_DIR and FREESURFER_HOME, see find.subjectsdir.of. If the subject is the template subject 'fsaverage' and it cannot be found, it is downloaded into the package cache.

subject_id

string. The subject identifier, used to load the context mesh. Defaults to 'fsaverage', the template subject for which the surfaces can be downloaded automatically.

volume

a 3D numerical array (or an fs.volume instance) with the data, e.g., a statistical map. Values are interpreted as signed, i.e., the clusters are the regions in which the value is above threshold or below -threshold. See the note on the coordinate system.

threshold

single positive number or NULL. The cluster threshold, applied to the absolute voxel values. If NULL (the default), it is computed from the data as the threshold_quantile quantile of the absolute values of the non-zero voxels, and the value is reported unless silent is TRUE.

threshold_quantile

single value between 0 and 1, the quantile of the absolute non-zero voxel values used as the threshold if threshold is NULL. Defaults to 0.95.

max_level

single positive number or NULL, the highest iso-level, i.e., the level of the innermost shell of every cluster, in the units of the volume data. If NULL (the default), a separate value is computed for the positive and the negative clusters, namely the max_level_quantile quantile of the absolute values of the voxels beyond the threshold, so that a single extreme voxel does not dominate the visualization.

max_level_quantile

single value between 0 and 1, the quantile of the supra-threshold voxel values used to compute max_level if that is NULL. Defaults to 0.99.

num_levels

positive integer, the number of nested shells per cluster, i.e., per sign. The outermost shell is at the threshold, the innermost at max_level. Defaults to 10. Pass 1 to render a single opaque shell per sign, see the note on the visual style.

positive

logical, whether to render the clusters above threshold. Defaults to TRUE.

negative

logical, whether to render the clusters below -threshold. Defaults to TRUE. At least one of positive and negative must be TRUE.

smoothing

non-negative integer, the number of 3x3x3 box blur passes applied to the volume before the shells are extracted. This removes the staircase artifacts of the marching cubes algorithm and is what makes the clusters look like smooth blobs. Defaults to 2. Set to 0 to extract the shells from the raw volume.

downsample

positive integer, a factor by which the volume is subsampled before the shells are extracted. Values larger than 1 reduce the number of triangles (and thus the rendering time) considerably, at the cost of a less detailed surface, which can be useful because a cluster is rendered as num_levels meshes. The coordinates of the subsampled shells are corrected, so the result remains aligned with the original volume. Defaults to 1. Note that the volume is smoothed before subsampling if smoothing is larger than 0, otherwise the shells are prone to aliasing artifacts.

frame

positive integer, the frame (4th dimension) to use for a 4D volume. Defaults to 1.

backend

character string, the backend used to extract the iso-surfaces, one of 'auto' (the default: use the Rvcg package if it is installed, and fall back to misc3d otherwise), 'Rvcg' or 'misc3d'. Rvcg is recommended, it is faster, which matters here because one mesh per shell is extracted.

context

NULL or the definition of the context mesh to render the clusters in, typically a semi-transparent cortex of the same subject. Supported values are a character string (the surface name, e.g., 'white' or 'pial'), a named list of options for the context mesh (entries 'surface', 'color', 'alpha', 'style', 'subjects_dir' and 'subject_id', see vis.subcortical.region.values), or a pre-built mesh (an fs.coloredmesh instance, or a hemilist of such instances).

alpha_range

numerical vector of length 2, the alpha value of the outermost shell (at the threshold) and of the innermost shell (at the cluster peak), each between 0 and 1. The values in between are interpolated, separately for the positive and the negative clusters. Defaults to c(0.08, 1.0), i.e., the boundary of a cluster is much more transparent than its core. See the note on the visual style.

makecmap_options

named list of parameters to pass to makecmap. Must not include the unnamed first parameter, which is derived from the data. The entry 'range' can be used to fix the range of the colormap, otherwise a symmetric range which covers all rendered iso-levels is used. Defaults to mkco.cluster.

views

list of character strings, the views to visualize. Available views are 'sd_<angle>' (a static view, see vis.subject.morph.native), 't4'/'t9' (a 2x2 or 3x3 lightbox of views) and 'si'/'sr' (single interactive / rotating, requires the rgl renderer backend). Defaults to the 4 standard lateral and medial views. Pass NULL to skip the rendering entirely and only compute the meshes (which are also returned).

rgloptions

option list passed to par3d. Defaults to the package default, see rglo.

rglactions

named list, passed to the visualization functions, see rglactions. The key 'no_vis' is useful to prepare the scene and add other data to it later. Note that saving the rendered scene to an image file is done with export, which takes the return value of this function and supports merging several views into one image.

silent

logical, whether to suppress the console messages which report the threshold, the levels and the backend used. Defaults to FALSE.

Value

the list of renderable meshes, invisibly: the context meshes (if any) first, then the cluster shells, ordered from the outermost to the innermost shell of each sign. Passing this list to export saves the scene as an image, including the colorbar of the cluster values.

Coordinate system

The cluster shells are extracted in the voxel space of the volume and transformed to surface RAS with index2ras_tkr, so they are aligned with surface renderings of the same subject. This requires the volume to be in the standard FreeSurfer orientation with 1 mm voxels (a conformed volume), which is the case for volumes read with subject.volume; volumes in other spaces (like a 2 mm MNI template) have to be transformed to the subject space outside of fsbrain first.

Visual style

A single iso-surface contains, by definition, the threshold value at all of its vertices, so a color gradient within one shell is not meaningful. The value information is therefore encoded in the nesting: each shell is drawn in the color of its own iso-level (the outer shell in the color of the threshold, the innermost one in the color of the peak), and the shells are semi-transparent, with the transparency decreasing towards the core (see alpha_range). This results in a soft glow which is brightest at the location of the maximum. Setting num_levels = 1 instead renders one fully opaque shell per sign (the cluster boundary), which is the cleanest option if only the extent of the clusters matters. Note that the backfaces of the shells are drawn (back = 'filled'): with culled backfaces, the rgl renderer would composite the nested transparent shells in the wrong order, so the innermost shell would end up on top of the outer ones.

Performance

A cluster is rendered as num_levels meshes, so the number of iso-surfaces that have to be extracted is num_levels times the number of signs (20 for the defaults). For a conformed volume of 256^3 voxels this takes about 30 seconds with the Rvcg backend, most of which is the marching cubes extraction. Setting downsample = 2 reduces this to a few seconds (and the number of triangles by roughly a factor of 8), which is usually not visible for the smooth blobs that the default smoothing produces; it is a good choice for larger volumes, for small num_levels it matters less.

See Also

volvis.shells to visualize a whole volume (not just the clusters) as nested shells, volvis.voxels for a voxel-based rendering, vis.volume.on.surface to combine a volume with a morphometry-colored surface, and vis.subcortical.region.values for the related atlas version with one value per region.

Other visualization functions: highlight.vertices.on.subject(), highlight.vertices.on.subject.spheres(), vis.color.on.subject(), vis.data.on.fsaverage(), vis.data.on.subject(), vis.labeldata.on.subject(), vis.mask.on.subject(), vis.region.values.on.subject(), vis.rglwidget(), vis.subcortical.region.values(), vis.subject.annot(), vis.subject.label(), vis.subject.morph.native(), vis.subject.morph.standard(), vis.subject.pre(), vis.symmetric.data.on.subject(), vis.volume.on.surface(), vislayout.from.coloredmeshes()

Other volume visualization: vis.volume.on.surface(), volvis.lb(), volvis.lb.with.surface(), volvis.lightbox(), volvis.slices.with.surface()

Examples

## Not run: 
   fsbrain::download_optional_data();
   fsbrain::download_fsaverage(accept_freesurfer_license = TRUE);
   subjects_dir = fsbrain::get_optional_data_filepath("subjects_dir");

   # Use the brain volume of the demo subject as a fake statistical map: bright voxels are
   # 'positive', dark ones are 'negative'.
   brain = subject.volume(subjects_dir, 'subject1', 'brain');
   stat = (brain - 110) / 30;

   # Render the clusters inside a semi-transparent cortex of the fsaverage template subject:
   cm = vis.volume.clusters(subjects_dir, 'fsaverage', stat, threshold = 1.5,
       rglactions = list('no_vis' = TRUE));
   export(cm, colorbar_legend = 'value', output_img = 'clusters.png');

   # A single opaque shell per cluster, which only shows the cluster extent:
   cm_simple = vis.volume.clusters(subjects_dir, 'fsaverage', stat, threshold = 1.5,
       num_levels = 1, rglactions = list('no_vis' = TRUE));

   # Without any context mesh, and with a fixed colormap range:
   cm_ctx = vis.volume.clusters(subjects_dir, 'fsaverage', stat, threshold = 1.5,
       context = NULL, makecmap_options = list('colFn' = squash::blueorange, 'n' = 100L,
           'symm' = TRUE, 'range' = c(-2.0, 2.0)), rglactions = list('no_vis' = TRUE));

## End(Not run)


fsbrain documentation built on Sept. 27, 2026, 1:07 a.m.