Voxel Performance Tradeoffs¶
NiiVue is designed to deliver smooth, interactive graphics on a wide range of devices, including low-power phones, tablets, and computers. Some visualization options, however, require additional resources and can reduce rendering performance—especially when displaying high resolution volume rendering. This notebook intentionally demonstrates these performance trade-offs, allowing you to explore them interactively through various controls. Features such as anti-aliasing, high-DPI rendering, and reflective volume modes are particularly demanding and can significantly affect speed on slower hardware.
This notebook mirrors the JavaScript web page.
In [1]:
import json
import ipywidgets as widgets
from ipyniivue import NiiVue
from ipyniivue.constants import ShowRender
## create user interface
status_bar = widgets.Label(value="")
aa_check = widgets.Checkbox(value=True, description="Anti Alias")
dpi_check = widgets.Checkbox(value=True, description="High DPI")
render_mode = widgets.Dropdown(
options=[
("slices", "-1"),
("matte", "0"),
("low", "0.3"),
("medium", "0.6"),
("high", "1.0"),
],
value="0.6",
description="Render Mode",
)
atlas_slider = widgets.IntSlider(
value=64, min=0, max=255, description="Atlas", readout=False
)
stat_slider = widgets.IntSlider(
value=255, min=0, max=255, description="Statistics", readout=False
)
# create niivue instance
with open( "../images/aal.json") as f:
cmap = json.load(f)
nv = None # Global variable to hold the NiiVue instance
def create_nv(anti_alias):
"""Create new NiiVue instance."""
global nv
if nv:
# Don't forget to dispose of the previous nv if it exists
nv.close()
nv = NiiVue(
back_color=(1, 1, 1, 1),
show_3d_crosshair=True,
is_anti_alias=anti_alias,
)
@nv.on_location_change
def handle_location_change(location):
"""Display location."""
status_bar.value = location["string"]
nv.opts.multiplanar_show_render = ShowRender.ALWAYS
nv.opts.is_colorbar = True
volume_list = [
{"path": "../images/mni152.nii.gz"},
{"path": "../images/aal.nii.gz"},
{
"path": "../images/stats.nv_demo_mskd.nii.gz",
"colormap": "warm",
"colormap_negative": "winter",
"frame_4d": 1,
"cal_min": 3.3641,
"cal_max": 6,
},
]
nv.load_volumes(volume_list)
# Hide colorbars for volumes 0 and 1
nv.volumes[0].colorbar_visible = False
nv.volumes[1].colorbar_visible = False
nv.volumes[1].set_colormap_label(cmap)
return nv
# Create initial nv
nv = create_nv(aa_check.value)
## Define event handlers
def on_dpi_check_change(change):
"""Set high resolution capable."""
nv.set_high_resolution_capable(change["new"])
def on_render_mode_change(change):
"""Set volume render illumination."""
nv.set_volume_render_illumination(float(change["new"]))
def on_atlas_slider_change(change):
"""Set 2nd volume opacity."""
nv.volumes[1].opacity = change["new"] / 255.0
def on_stat_slider_change(change):
"""Set 3rd volume opacity."""
nv.volumes[2].opacity = change["new"] / 255.0
def on_aa_check_change(change):
"""Recreate nv with new anti_alias setting and re-apply settings."""
anti_alias = change["new"]
# Create new nv
new_nv = create_nv(anti_alias)
# Update the UI container
ui_container.children = (
widgets.HBox([aa_check, dpi_check, render_mode]),
widgets.HBox([atlas_slider, stat_slider]),
new_nv,
status_bar,
)
# Re-apply settings, except for antialias, because doing
# so would result in an endless loop here
on_dpi_check_change({"new": dpi_check.value})
on_atlas_slider_change({"new": atlas_slider.value})
on_stat_slider_change({"new": stat_slider.value})
## Set up observers
dpi_check.observe(on_dpi_check_change, names="value")
render_mode.observe(on_render_mode_change, names="value")
atlas_slider.observe(on_atlas_slider_change, names="value")
stat_slider.observe(on_stat_slider_change, names="value")
aa_check.observe(on_aa_check_change, names="value")
## Apply initial settings
# Except for antialias, because doing so would result in an endless loop here
# Also, not doing on_render_mode_change because canvas has not been attached yet
# so gl does not exist yet.
on_dpi_check_change({"new": dpi_check.value})
on_atlas_slider_change({"new": atlas_slider.value})
on_stat_slider_change({"new": stat_slider.value})
## Display all
ui_container = widgets.VBox(
[
widgets.HBox([aa_check, dpi_check, render_mode]),
widgets.HBox([atlas_slider, stat_slider]),
nv,
status_bar,
]
)
display(ui_container)
In [ ]:
In [ ]: