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)
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)
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)