#| label: setup #| include: false knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE )
ggseg3d widgets work in Shiny applications. This vignette covers the output and render functions, plus reactive updates.
#| label: load-packages library(shiny) library(ggseg3d)
Use ggseg3dOutput() in the UI and renderGgseg3d() in the server:
#| label: basic-app ui <- fluidPage( titlePanel("Brain Atlas Viewer"), sidebarLayout( sidebarPanel( selectInput( "hemi", "Hemisphere", choices = c("left", "right", "both"), selected = "left" ) ), mainPanel( ggseg3dOutput("brain", height = "500px") ) ) ) server <- function(input, output, session) { output$brain <- renderGgseg3d({ hemi <- if (input$hemi == "both") NULL else input$hemi ggseg3d(hemisphere = hemi) |> pan_camera("left lateral") }) } shinyApp(ui, server)
Set explicit dimensions in ggseg3dOutput():
#| label: output-sizing ggseg3dOutput("brain", width = "100%", height = "600px")
Or use set_dimensions() in the render function:
#| label: render-dimensions renderGgseg3d({ ggseg3d() |> set_dimensions(width = 800, height = 600) })
Update the brain plot when data changes:
#| label: reactive-data server <- function(input, output, session) { brain_data <- reactive({ tibble( region = c("precentral", "postcentral", "insula"), value = runif(3) ) }) output$brain <- renderGgseg3d({ ggseg3d( .data = brain_data(), atlas = dk(), # nolint [object_usage_linter] colour_by = "value" ) |> pan_camera("left lateral") }) }
Use updateGgseg3dCamera() and updateGgseg3dBackground() to modify an existing widget without re-rendering:
#| label: reactive-updates ui <- fluidPage( sidebarLayout( sidebarPanel( selectInput( "view", "View", choices = c( "left lateral", "left medial", "right lateral", "right medial" ) ), selectInput("bg", "Background", choices = c("white", "black", "grey")) ), mainPanel( ggseg3dOutput("brain") ) ) ) server <- function(input, output, session) { output$brain <- renderGgseg3d({ ggseg3d() |> pan_camera("left lateral") }) observeEvent(input$view, { updateGgseg3dCamera("brain", input$view) }) observeEvent(input$bg, { updateGgseg3dBackground("brain", input$bg) }) }
These updates are faster than re-rendering the entire widget.
Here's a full app with data selection and dynamic updates:
#| label: complete-app library(shiny) library(ggseg3d) library(dplyr) example_data <- tibble( region = c( "precentral", "postcentral", "insula", "superior parietal", "inferior parietal", "supramarginal", "cuneus", "pericalcarine" ), thickness = c(2.5, 2.3, 3.1, 2.2, 2.4, 2.6, 1.8, 1.9), volume = c(8500, 7200, 6800, 9100, 8800, 7500, 4200, 3800) ) ui <- fluidPage( titlePanel("Brain Metrics Explorer"), sidebarLayout( sidebarPanel( selectInput("metric", "Metric", choices = c("thickness", "volume")), selectInput( "view", "Camera View", choices = c( "left lateral", "left medial", "right lateral", "right medial", "left superior", "left inferior" ) ), checkboxInput("edges", "Show edges", value = FALSE), selectInput("bg", "Background", choices = c("white", "black", "grey90")) ), mainPanel( ggseg3dOutput("brain", height = "600px") ) ) ) server <- function(input, output, session) { output$brain <- renderGgseg3d({ p <- ggseg3d( .data = example_data, atlas = dk(), # nolint [object_usage_linter] colour_by = input$metric, text_by = input$metric ) |> pan_camera(input$view) |> set_background(input$bg) if (input$edges) { p <- p |> set_edges("black") } p }) } shinyApp(ui, server)
Minimize re-renders: Use updateGgseg3dCamera() and updateGgseg3dBackground() for camera and background changes instead of re-rendering.
Debounce reactive data: If data updates frequently, use debounce() to avoid excessive re-renders.
Pre-compute data: Do data transformations outside the render function when possible.
Limit regions: Showing fewer regions renders faster. Filter your atlas if you only need specific structures.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.