Time Series¶

This jupyter script loads a series of arterial spin labeling (ASL) images. The slider lets you view a single 3D volume from a 4D timeseries dataset. The accompanying graph displays the voxel intensity over time for the voxel located at the crosshairs.

This script also highlights an important feature of ipyniivue: image and mesh loading occurs asynchronously. As a result, the load_volumes() function returns before the dataset is fully ready, meaning the number of volumes in the timeseries cannot be determined immediately. To correctly configure the slider range, an on_image_loaded() callback is used. This event triggers once the image has finished loading and is ready for use. Although this asynchronous behavior is uncommon in typical Python workflows, it ensures the web interface remains responsive during file loading.

This Python code closely mirrors the functionality of the time series web page

In [1]:
import ipywidgets as widgets
from ipyniivue import NiiVue, SliceType, ShowRender

nv = NiiVue(slice_type=SliceType.MULTIPLANAR)

@nv.on_image_loaded
def on_image_loaded(volume):
    """
    Event handler called when an image is loaded.

    Parameters
    ----------
    volume : ipyniivue.Volume
        The loaded image volume.
    """
    nvols = volume.n_frame_4d
    slider.max = nvols - 1

nv.load_volumes([{"path": "../images/mpld_asl.nii.gz"}])

nv.opts.multiplanar_show_render = ShowRender.ALWAYS
nv.graph.auto_size_multiplanar = True
nv.graph.normalize_values = False
nv.graph.opacity = 1.0
slider = widgets.IntSlider(min=0, max=0, description="Volume")

def update_frame(*args):
    """Select the frame corresponding to the slider value."""
    nv.volumes[0].frame_4d = slider.value


slider.observe(update_frame, "value")

dark_checkbox = widgets.Checkbox(
    value=True, description="Dark", tooltip="Toggle background color"
)

def on_dark_change(change):
    """Handle nose direction checkbox changes."""
    if change["new"]:
        nv.opts.back_color = (0, 0, 0, 1)
    else:
        nv.opts.back_color = (1, 1, 1, 1)

dark_checkbox.observe(on_dark_change, names="value")


controls = widgets.HBox([dark_checkbox, slider])

display(widgets.VBox([controls, nv]))
In [ ]:
 
In [ ]: