Mesh 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 meshes with very large numbers of vertices instead of simplified models. 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 X-Ray modes are particularly demanding and can significantly affect speed on slower hardware.
This notebook mirrors the JavaScript web page.
In [1]:
from ipyniivue import NiiVue
import ipywidgets as widgets
nv = None # Global variable to hold the NiiVue instance
def create_nv(anti_alias = True):
"""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_mesh_loaded
def on_mesh_loaded(volume):
nv.meshes[1].colorbar_visible = False
nv.opts.show_legend = False
on_curv_change({"new": slider_curv.value})
on_atlas_change({"new": slider_atlas.value})
on_stat_change({"new": slider_stat.value})
on_dpi_check_change({"new": dpi_check.value})
on_shader_change({"new": shader_dropdown.value})
on_alpha_change({"new": alpha_dropdown.value})
on_xray_change({"new": slider_xray.value})
mesh_layers = [
{
"path": "../images/lh.curv",
"cal_min": 0.3,
"cal_max": 0.5,
"colormap": "gray",
"opacity": 222 / 255,
},
{
"path": "../images/boggle.lh.annot",
"opacity": 0.33,
},
{
"path": "../images/pval.LH.nii.gz",
"cal_min": 25,
"cal_max": 35,
"opacity": 1,
},
]
nv.load_meshes(
[
{
"path": "../images/CIT168.mz3",
},
{
"path": "../images/lh.pial",
"layers": mesh_layers,
}
]
)
return nv
# Create initial nv
nv = create_nv()
## User interface
aa_check = widgets.Checkbox(value=True, description="Anti Alias")
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, slider_xray]),
widgets.HBox([slider_curv, slider_atlas, slider_stat]),
widgets.HBox([shader_dropdown, alpha_dropdown]),
new_nv
)
aa_check.observe(on_aa_check_change, names="value")
dpi_check = widgets.Checkbox(value=True, description="High DPI")
def on_dpi_check_change(change):
"""Set high resolution capable."""
nv.set_high_resolution_capable(change["new"])
dpi_check.observe(on_dpi_check_change, names="value")
slider_curv = widgets.IntSlider(min=0, max=255, value=222, description="Curve", readout=False)
def on_curv_change(change):
"""Set curvature layer opacity."""
nv.set_mesh_layer_property(nv.meshes[1].id, 0, "opacity", change["new"] / 255)
slider_curv.observe(on_curv_change, names="value")
slider_atlas = widgets.IntSlider(min=1, max=255, value=84, description="Atlas", readout=False)
def on_atlas_change(change):
"""Set atlas layer opacity."""
nv.set_mesh_layer_property(nv.meshes[1].id, 1, "opacity", change["new"] / 255)
slider_atlas.observe(on_atlas_change, names="value")
slider_stat = widgets.IntSlider(min=1, max=255, value=255, description="Stat", readout=False)
def on_stat_change(change):
"""Set stat layer opacity."""
nv.set_mesh_layer_property(nv.meshes[1].id, 2, "opacity", change["new"] / 255)
slider_stat.observe(on_stat_change, names="value")
slider_xray = widgets.IntSlider(min=0, max=30, value=0, description="XRay", readout=False)
def on_xray_change(change):
"""Set mesh xray."""
nv.opts.mesh_xray = change["new"] * 0.01
slider_xray.observe(on_xray_change, names="value")
shader_options = nv.mesh_shader_names()
shader_dropdown = widgets.Dropdown(
options=shader_options,
value="Phong", # Default shader
description="Shader:",
)
def on_shader_change(change):
"""Set mesh layer shader."""
nv.set_mesh_shader(nv.meshes[1].id, change["new"])
shader_dropdown.observe(on_shader_change, names="value")
alpha_options = ["Opaque", "Translucent", "Transparent"]
alpha_dropdown = widgets.Dropdown(
options=alpha_options,
value="Translucent",
description="Opacity:",
)
def on_alpha_change(change):
"""Set mesh layer shader."""
idx = 1
value = change["new"]
if (value == "Opaque"):
nv.meshes[idx].opacity = 1.0
if (value == "Translucent"):
nv.meshes[idx].opacity = 0.2
if (value == "Transparent"):
nv.meshes[idx].opacity = 0.0
# TODO: draw_scene causes error if no voxels loaded
# nv.draw_scene()
nv.set_mesh_shader(nv.meshes[0].id, shader_dropdown.value)
alpha_dropdown.observe(on_alpha_change, names="value")
ui_container = widgets.VBox(
[
widgets.HBox([aa_check, dpi_check, slider_xray]),
widgets.HBox([slider_curv, slider_atlas, slider_stat]),
widgets.HBox([shader_dropdown, alpha_dropdown]),
nv
]
)
## Display user interface and meshes
display(ui_container)
In [ ]:
In [ ]: