Atlas Demo¶
NiiVue can display brain atlases interactively, showing the region name when you hover over an area and adjusting opacity to highlight the selected region.
This notebook mirrors the Atlas live demo web page
In [1]:
import json
import ipywidgets as widgets
from IPython.display import display
from ipyniivue import NiiVue, ShowRender
## Create NiiVue Instance
nv = NiiVue(
show_3d_crosshair=True,
back_color=(0.5, 0.5, 0.5, 1),
)
nv.set_interpolation(True)
nv.opts.crosshair_gap = 12
nv.opts.multiplanar_show_render = ShowRender.ALWAYS
nv.opts.drag_mode = "PAN"
nv.opts.yoke_3d_to_2d_zoom = True
nv.load_volumes(
[
{"path": "../images/mni152.nii.gz"},
{"path": "../images/aal.nii.gz"},
]
)
## Load a custom colormap
with open("../images/aal.json") as f:
cmap = json.load(f)
nv.volumes[1].set_colormap_label(cmap)
clut = nv.volumes[1].colormap_label.lut.copy()
# Make all regions translucent by setting alpha values to 96
for i in range(3, len(clut), 4):
clut[i] = 96
# Update the colormap label with the modified lut
nv.volumes[1].colormap_label.lut = clut
## Add other widgets
interp_checkbox = widgets.Checkbox(
value=True,
description="Jagged",
)
outline_slider = widgets.IntSlider(
min=0,
max=255,
value=1,
description="Outline",
)
alpha_slider = widgets.IntSlider(
min=1,
max=255,
value=150,
description="Opacity",
)
pad_slider = widgets.IntSlider(
min=0,
max=10,
value=5,
description="Padding",
)
gap_slider = widgets.IntSlider(
min=0,
max=36,
value=12,
description="Crosshair Gap",
style={"description_width": "initial"}
)
## Setup observer functions
def on_outline_change(change):
"""Handle changes in the outline slider."""
nv.set_atlas_outline(change["new"] / 255)
def on_alpha_change(change):
"""Handle changes in the opacity slider."""
nv.volumes[1].opacity = change["new"] / 255
def on_pad_change(change):
"""Handle changes in the padding slider."""
nv.opts.multiplanar_pad_pixels = change["new"]
def on_gap_change(change):
"""Handle changes in the crosshair gap slider."""
nv.opts.crosshair_gap = change["new"]
def on_interp_change(change):
"""Handle changes in the interpolation checkbox."""
nv.set_interpolation(change["new"])
# Observe changes in widget values and call the respective functions
outline_slider.observe(on_outline_change, names="value")
alpha_slider.observe(on_alpha_change, names="value")
pad_slider.observe(on_pad_change, names="value")
gap_slider.observe(on_gap_change, names="value")
interp_checkbox.observe(on_interp_change, names="value")
# Initialize the NiiVue instance with the current widget values
on_alpha_change({"new": alpha_slider.value})
on_outline_change({"new": outline_slider.value})
nv.opts.multiplanar_pad_pixels = pad_slider.value
nv.opts.crosshair_gap = gap_slider.value
nv.set_interpolation(interp_checkbox.value)
## Setup hover and click updates
output = widgets.HTML("Hover:<br>Clicked:")
active_idx = -1
@nv.on_hover_idx_change
def on_hover_idx_change(data):
"""Handle hover updates."""
global active_idx
idx_values = data["idxValues"]
idx = idx_values[1]["idx"]
if idx is not None and idx != active_idx:
nv.opts.atlas_active_index = idx
label = cmap["labels"][idx] if idx < len(cmap["labels"]) else ""
clicked_line = output.value.split("Clicked:")[1]
output.value = f"Hover: {label}<br>Clicked:{clicked_line}"
@nv.on_location_change
def handle_location_change(location):
"""Handle mouse clicks."""
hover_line = output.value.split("Hover:")[1].split("<br>")[0]
output.value = f"Hover:{hover_line}<br>Clicked: {location['string']}"
## Display all
controls = widgets.VBox(
[
interp_checkbox,
outline_slider,
alpha_slider,
pad_slider,
gap_slider,
output,
]
)
display(
widgets.VBox(
[
controls,
nv,
]
)
)
In [ ]: