Download PDF
3D brain plotting with ggseg3d :: Cheatsheet
Interactive brain surfaces as an htmlwidget
Plotting
A brain in three dimensions
ggseg3d renders an atlas onto a brain mesh and returns an htmlwidget — draggable in RStudio, a Quarto document or a Shiny app.
library(ggseg3d)
ggseg3d(atlas = dk()) |>
pan_camera("left lateral")ggseg3d(
.data = NULL, atlas = dk(),
label_by = "region", text_by = NULL,
colour_by = "colour", palette = NULL,
na_colour = "darkgrey", na_alpha = 1, ...
)- Atlases are functions:
dk(), notdk. - The result is a widget. Every option below is a pipe step, not an argument.
label_bysets the hover label,text_byadds a second hover line.
Your data on the surface
Pass a data frame with a region column and name the column to colour by.
scores <- data.frame(
region = c("precentral", "insula"),
score = c(1.2, -0.4)
)
ggseg3d(
.data = scores,
atlas = dk(),
colour_by = "score",
palette = c("#f2f0ef", "#5e3c58")
) |>
pan_camera("left lateral")palettetakes colour names or hex codes, interpolated across the range.- A named numeric palette pins colours to values:
c("#f2f0ef" = 0, "#5e3c58" = 3). - Regions missing from
.datatakena_colour;na_alphafades them.
How each atlas type is drawn
| Type | Mesh | Colouring |
|---|---|---|
| cortical | one shared mesh per hemisphere | per vertex |
| cerebellar | one shared SUIT mesh | per vertex |
| subcortical | one mesh per structure | per face |
| tract | tube meshes built at render time | by orientation |
Tract atlases encode direction as colour: red left–right, green anterior–posterior, blue superior–inferior.
Positioning
Cameras
ggseg3d(atlas = dk()) |>
pan_camera("right medial")
# or an explicit x, y, z position
ggseg3d(atlas = dk()) |>
pan_camera(c(-350, 0, 0))Presets are "<hemisphere> <view>", with an underscore accepted in place of the space:
| lateral | medial | superior | inferior | anterior | posterior | |
|---|---|---|---|---|---|---|
| left | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| right | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Which hemispheres and surfaces
ggseg3d(atlas = dk(), hemisphere = "left")
ggseg3d(atlas = dk(), surface = "pial")"inflated" is the default and ships with ggseg.formats. The rest come from ggseg.meshes, an optional install:
install.packages(
"ggseg.meshes",
repos = "https://ggsegverse.r-universe.dev"
)
ggseg.meshes::available_cortical_surfaces()
#> pial, white, midthickness, semi-inflated,
#> sphere, smoothwm, orig
ggseg.meshes::available_cerebellar_surfaces()
#> suit_flatresolve_brain_mesh(hemisphere, surface, brain_meshes) is the single entry point — pass brain_meshes to render on a mesh of your own.
A glass brain around a subcortical atlas
ggseg3d(atlas = aseg()) |>
add_glassbrain("left", opacity = 0.2) |>
pan_camera("left lateral")add_glassbrain(
p, hemisphere = c("left", "right"),
surface = "inflated", colour = "#CCCCCC",
opacity = 0.3, brain_meshes = NULL
)Appearance
Widget options
Every one of these takes the widget and returns it, so they chain.
ggseg3d(atlas = dk()) |>
set_background("#1a2a2e") |>
set_edges(colour = "white", width = 1) |>
set_legend(show = FALSE) |>
set_dimensions(width = 800, height = 600) |>
set_flat_shading(flat = TRUE) |>
set_orthographic(ortho = TRUE, frustum_size = 220) |>
set_positioning("centered") |>
pan_camera("left lateral")| Step | Does |
|---|---|
set_background() |
canvas colour |
set_edges() |
region boundary lines |
set_legend() |
show or hide the colour legend |
set_dimensions() |
widget size in pixels |
set_flat_shading() |
faceted rather than smooth shading |
set_orthographic() |
drop perspective |
set_positioning() |
"anatomical" or "centered" |
Saving a still image
ggseg3d(atlas = dk()) |>
pan_camera("left lateral") |>
snapshot_brain(
"brain.png",
width = 600, height = 500, zoom = 2
)snapshot_brain() drives a headless browser, so it needs webshot2 and Chrome. For a plot destined for print, ggsegray() renders the same scene through rgl instead:
ggsegray(atlas = dk(), colour_by = "colour") |>
pan_camera("right lateral")Shiny
Widget bindings
ui <- fluidPage(
ggseg3dOutput(
"brain",
width = "100%",
height = "600px"
)
)
server <- function(input, output, session) {
output$brain <- renderGgseg3d({
ggseg3d(
.data = scores(),
atlas = dk(),
colour_by = "score"
)
})
}Other atlases
Every atlas on the r-universe works the same way, so long as it carries 3D data. plot(atlas) and the atlas’s own print method say whether it does.
install_ggseg_atlas("ggsegYeo2011")
library(ggsegYeo2011)
ggseg3d(atlas = yeo7()) |>
pan_camera("left lateral")A cortical atlas built only from 2D polygons has no vertices, and ggseg3d errors rather than guessing at them.
Cerebellum and tracts
# cerebellum, on the shared SUIT mesh
ggseg3d(atlas = suit())
# tracts, coloured by orientation
ggseg3d(atlas = tracula()) |>
add_glassbrain(opacity = 0.1)Updating without a redraw
Rebuilding the widget reloads the whole mesh. These proxies change one thing in place:
updateGgseg3dCamera(session, "brain", "right lateral")
updateGgseg3dBackground(session, "brain", "#1a2a2e")Gotchas
dkis a function;dk()is the atlas.label,textandcolourwere renamed tolabel_by,text_byandcolour_byin 2.1.0. The old names still work, with a warning.- A widget cannot be printed to PDF. Use
snapshot_brain()orggsegray()for static output. - Cortical meshes share vertex indices across regions and so cannot be decimated; subcortical meshes can.
- Asking for a non-
"inflated"surface without ggseg.meshes installed is an error, not a silent fallback.
In documents
A widget needs a JavaScript-capable output. In Quarto and R Markdown it works in html formats, and in pdf only through a static snapshot:
```{r}
#| eval: false
ggseg3d(atlas = dk())
```Guard it when a document renders to both:
#| eval: !expr knitr::is_html_output()Each widget carries its own copy of the mesh, so a page with many brains gets heavy quickly — prefer one widget the reader can rotate over a grid of static views.
Colour and legend
colour_by names the column to map; palette says how.
# interpolated across the data range
palette = c("#f2f0ef", "#a8c5cb", "#5e3c58")
# pinned to specific values
palette = c(
"#f2f0ef" = 0,
"#a8c5cb" = 1.5,
"#5e3c58" = 3
)Leave colour_by = "colour" — the default — to draw the atlas in its own palette instead. set_legend(FALSE) drops the colour bar when the figure has its own caption.
Hover text
ggseg3d(
.data = scores,
atlas = dk(),
colour_by = "score",
label_by = "region",
text_by = "score"
)label_by is the bold first line of the tooltip, text_by a second line below it. Both name columns of .data or of the atlas core.
2D or 3D?
| Want | Reach for |
|---|---|
| a figure for a paper | ggseg |
| a brain readers can rotate | ggseg3d |
| cortical surface anatomy | ggseg3d, inflated or pial |
| subcortical slices | ggseg, aseg() |
| subcortical volumes in space | ggseg3d, aseg() |
| tract orientation | ggseg3d, tracula() |
When nothing appears
- Blank panel in RStudio. The widget needs the Viewer pane; try
print()in a browser withhtmlwidgets::saveWidget(). - Everything grey. No region in
.datamatched the atlas. Compareunique(.data$region)withatlas_regions(atlas). - An error about vertices. The atlas has 2D geometry only. Use ggseg, or rebuild the atlas with ggseg.extra.
- Slow first draw. The mesh is loaded once per session; later widgets on the same surface are quicker.
Learn more
https://ggsegverse.github.io— ecosystem documentationvignette("ggseg3d")— longer worked exampleshttps://github.com/ggsegverse/ggseg3d— source and issues
