Example #1
0
def visualize_volume(volume,
                     figure=None,
                     show_x=True,
                     show_y=True,
                     show_z=True,
                     interact=False,
                     inline=False,
                     opacity=0.3,
                     flip_axes=[False, False, False],
                     slider_definition=20,
                     which_plane=None):
    """
    Visualize a volume

    Parameters
    ----------
    volume : ndarray or str
        3d volume to visualize.

    figure : Plotly Figure object, optional
        If provided, the visualization will be added to this Figure. Default:
        Initialize a new Figure.

    show_x : bool, optional
        Whether to show Coronal Slice.
        Default: True

    show_x : bool, optional
        Whether to show Sagittal Slice.
        Default: True

    show_x : bool, optional
        Whether to show Axial Slice.
        Default: True

    opacity : float, optional
        Opacity of slices.
        Default: 1.0

    flip_axes : ndarray
        Which axes to flip, to orient the image as RAS, which is how we
        visualize.
        For example, if the input image is LAS, use [True, False, False].
        Default: [False, False, False]

    slider_definition : int, optional
        How many discrete positions the slices can take.
        If 0, slices are stationary.
        Default: 50

    which_plane : str, optional
        Which plane can be moved with a slider.
        Should be 'Coronal', 'Axial', 'Sagittal', or None.
        If None, slices are stationary.
        Note: If slices are not stationary,
        do not add any more traces to the figure.
        Default: 'Coronal'

    interact : bool
        Whether to open the visualization in an interactive window.
        Default: False

    inline : bool
        Whether to embed the interactive visualization inline in a notebook.
        Only works in the notebook context. Default: False.

    Returns
    -------
    Plotly Figure object
    """
    volume = vut.load_volume(volume)
    for i, flip in enumerate(flip_axes):
        if flip:
            volume = np.flip(volume, axis=i)

    if figure is None:
        figure = go.Figure()

    set_layout(figure)
    sliders = []

    # draw stationary slices first
    if show_x:
        if (which_plane is None) or which_plane.lower() != 'sagittal':
            _draw_slices(figure, Axes.X, volume, opacity=opacity, y_loc=0)
    if show_y:
        if (which_plane is None) or which_plane.lower() != 'coronal':
            _draw_slices(figure, Axes.Y, volume, opacity=opacity, y_loc=0)
    if show_z:
        if (which_plane is None) or which_plane.lower() != 'axial':
            _draw_slices(figure, Axes.Z, volume, opacity=opacity, y_loc=0)

    # Then draw interactive slices
    if show_x:
        if (which_plane is not None) and which_plane.lower() == 'sagittal':
            _draw_slices(figure,
                         Axes.X,
                         volume,
                         sliders=sliders,
                         opacity=opacity,
                         n_steps=slider_definition,
                         y_loc=0)
    if show_y:
        if (which_plane is not None) and which_plane.lower() == 'coronal':
            _draw_slices(figure,
                         Axes.Y,
                         volume,
                         sliders=sliders,
                         opacity=opacity,
                         n_steps=slider_definition,
                         y_loc=0)
    if show_z:
        if (which_plane is not None) and which_plane.lower() == 'axial':
            _draw_slices(figure,
                         Axes.Z,
                         volume,
                         sliders=sliders,
                         opacity=opacity,
                         n_steps=slider_definition,
                         y_loc=0)

    if slider_definition > 0 and which_plane is not None:
        figure.update_layout(sliders=tuple(sliders))

    return _inline_interact(figure, interact, inline)
Example #2
0
def visualize_volume(volume,
                     x=None,
                     y=None,
                     z=None,
                     figure=None,
                     flip_axes=None,
                     opacity=0.6,
                     inline=True,
                     interact=False):
    """
    Visualize a volume

    Parameters
    ----------
    volume : ndarray or str
        3d volume to visualize.

    figure : fury Scene object, optional
        If provided, the visualization will be added to this Scene. Default:
        Initialize a new Scene.

    flip_axes : None
        This parameter is to conform fury and plotly APIs.

    opacity : float, optional
        Initial opacity of slices.
        Default: 0.6

    interact : bool
        Whether to provide an interactive VTK window for interaction.
        Default: False

    inline : bool
        Whether to embed the visualization inline in a notebook. Only works
        in the notebook context. Default: False.

    Returns
    -------
    Fury Scene object
    """
    volume = vut.load_volume(volume)

    if figure is None:
        figure = window.Scene()

    shape = volume.shape
    image_actor_z = actor.slicer(volume)
    slicer_opacity = opacity
    image_actor_z.opacity(slicer_opacity)

    image_actor_x = image_actor_z.copy()
    if x is None:
        x = int(np.round(shape[0] / 2))
    image_actor_x.display_extent(x, x, 0, shape[1] - 1, 0, shape[2] - 1)

    image_actor_y = image_actor_z.copy()

    if y is None:
        y = int(np.round(shape[1] / 2))
    image_actor_y.display_extent(0, shape[0] - 1, y, y, 0, shape[2] - 1)

    figure.add(image_actor_z)
    figure.add(image_actor_x)
    figure.add(image_actor_y)

    show_m = window.ShowManager(figure, size=(1200, 900))
    show_m.initialize()

    if interact:
        line_slider_z = ui.LineSlider2D(min_value=0,
                                        max_value=shape[2] - 1,
                                        initial_value=shape[2] / 2,
                                        text_template="{value:.0f}",
                                        length=140)

        line_slider_x = ui.LineSlider2D(min_value=0,
                                        max_value=shape[0] - 1,
                                        initial_value=shape[0] / 2,
                                        text_template="{value:.0f}",
                                        length=140)

        line_slider_y = ui.LineSlider2D(min_value=0,
                                        max_value=shape[1] - 1,
                                        initial_value=shape[1] / 2,
                                        text_template="{value:.0f}",
                                        length=140)

        opacity_slider = ui.LineSlider2D(min_value=0.0,
                                         max_value=1.0,
                                         initial_value=slicer_opacity,
                                         length=140)

        def change_slice_z(slider):
            z = int(np.round(slider.value))
            image_actor_z.display_extent(0, shape[0] - 1, 0, shape[1] - 1, z,
                                         z)

        def change_slice_x(slider):
            x = int(np.round(slider.value))
            image_actor_x.display_extent(x, x, 0, shape[1] - 1, 0,
                                         shape[2] - 1)

        def change_slice_y(slider):
            y = int(np.round(slider.value))
            image_actor_y.display_extent(0, shape[0] - 1, y, y, 0,
                                         shape[2] - 1)

        def change_opacity(slider):
            slicer_opacity = slider.value
            image_actor_z.opacity(slicer_opacity)
            image_actor_x.opacity(slicer_opacity)
            image_actor_y.opacity(slicer_opacity)

        line_slider_z.on_change = change_slice_z
        line_slider_x.on_change = change_slice_x
        line_slider_y.on_change = change_slice_y
        opacity_slider.on_change = change_opacity

        def build_label(text):
            label = ui.TextBlock2D()
            label.message = text
            label.font_size = 18
            label.font_family = 'Arial'
            label.justification = 'left'
            label.bold = False
            label.italic = False
            label.shadow = False
            label.background = (0, 0, 0)
            label.color = (1, 1, 1)

            return label

        line_slider_label_z = build_label(text="Z Slice")
        line_slider_label_x = build_label(text="X Slice")
        line_slider_label_y = build_label(text="Y Slice")
        opacity_slider_label = build_label(text="Opacity")

        panel = ui.Panel2D(size=(300, 200),
                           color=(1, 1, 1),
                           opacity=0.1,
                           align="right")
        panel.center = (1030, 120)

        panel.add_element(line_slider_label_x, (0.1, 0.75))
        panel.add_element(line_slider_x, (0.38, 0.75))
        panel.add_element(line_slider_label_y, (0.1, 0.55))
        panel.add_element(line_slider_y, (0.38, 0.55))
        panel.add_element(line_slider_label_z, (0.1, 0.35))
        panel.add_element(line_slider_z, (0.38, 0.35))
        panel.add_element(opacity_slider_label, (0.1, 0.15))
        panel.add_element(opacity_slider, (0.38, 0.15))

        show_m.scene.add(panel)

        global size
        size = figure.GetSize()

        def win_callback(obj, event):
            global size
            if size != obj.GetSize():
                size_old = size
                size = obj.GetSize()
                size_change = [size[0] - size_old[0], 0]
                panel.re_align(size_change)

    show_m.initialize()

    figure.zoom(1.5)
    figure.reset_clipping_range()

    if interact:
        show_m.add_window_callback(win_callback)
        show_m.render()
        show_m.start()

    return _inline_interact(figure, inline, interact)
Example #3
0
def visualize_bundles(sft,
                      affine=None,
                      n_points=None,
                      bundle_dict=None,
                      bundle=None,
                      colors=None,
                      color_by_volume=None,
                      cbv_lims=[None, None],
                      flip_axes=[False, False, False],
                      figure=None,
                      background=(1, 1, 1),
                      interact=False,
                      inline=False):
    """
    Visualize bundles in 3D

    Parameters
    ----------
    sft : Stateful Tractogram, str
        A Stateful Tractogram containing streamline information
        or a path to a trk file.
        In order to visualize individual bundles, the Stateful Tractogram
        must contain a bundle key in it's data_per_streamline which is a list
        of bundle `'uid'`.

    affine : ndarray, optional
       An affine transformation to apply to the streamlines before
       visualization. Default: no transform.

    n_points : int or None
        n_points to resample streamlines to before plotting. If None, no
        resampling is done.

    bundle_dict : dict, optional
        Keys are names of bundles and values are dicts that should include
        a key `'uid'` with values as integers for selection from the sft
        metadata. Default: bundles are either not identified, or identified
        only as unique integers in the metadata.

    bundle : str or int, optional
        The name of a bundle to select from among the keys in `bundle_dict`
        or an integer for selection from the sft metadata.

    colors : dict or list
        If this is a dict, keys are bundle names and values are RGB tuples.
        If this is a list, each item is an RGB tuple. Defaults to a list
        with Tableau 20 RGB values if bundle_dict is None, or dict from
        bundles to Tableau 20 RGB values if bundle_dict is not None.

    color_by_volume : ndarray or str, optional
        3d volume use to shade the bundles. If None, no shading
        is performed. Only works when using the plotly backend.
        Default: None

    cbv_lims : ndarray
        Of the form (lower bound, upper bound). Shading based on
        color_by_volume will only differentiate values within these bounds.
        If lower bound is None, will default to 0.
        If upper bound is None, will default to the maximum value in
        color_by_volume.
        Default: [None, None]

    flip_axes : ndarray
        Which axes to flip, to orient the image as RAS, which is how we
        visualize.
        For example, if the input image is LAS, use [True, False, False].
        Default: [False, False, False]

    background : tuple, optional
        RGB values for the background. Default: (1, 1, 1), which is white
        background.

    figure : Plotly Figure object, optional
        If provided, the visualization will be added to this Figure. Default:
        Initialize a new Figure.

    interact : bool
        Whether to open the visualization in an interactive window.
        Default: False

    inline : bool
        Whether to embed the interactivevisualization inline in a notebook.
        Only works in the notebook context. Default: False.

    Returns
    -------
    Plotly Figure object
    """

    if color_by_volume is not None:
        color_by_volume = vut.load_volume(color_by_volume)

    if figure is None:
        figure = go.Figure()

    set_layout(figure, color=_color_arr2str(background))

    for (sls, color, name,
         dimensions) in vut.tract_generator(sft, affine, bundle, bundle_dict,
                                            colors, n_points):
        _draw_streamlines(figure,
                          sls,
                          dimensions,
                          color,
                          name,
                          cbv=color_by_volume,
                          cbv_lims=cbv_lims,
                          flip_axes=flip_axes)

    figure.update_layout(legend=dict(itemsizing="constant"))
    return _inline_interact(figure, interact, inline)