Source code for dipy.viz.horizon.tab.peak

from functools import partial
from pathlib import Path

import numpy as np

from dipy.testing.decorators import is_macOS, warning_for_keywords
from dipy.viz.horizon.tab import (
    HorizonTab,
    build_checkbox,
    build_label,
    build_radio_button,
    build_slider,
)


[docs] class PeaksTab(HorizonTab): def __init__(self, peak_actor, title, fname): """Initialize Interaction tab for peaks visualization. Parameters ---------- peak_actor : PeaksActor Horizon PeaksActor visualize peaks. title : str Title of the tab. fname : str Filename of the peaks file. """ super().__init__() self._actor = peak_actor self._name = title self._file_name = Path(fname or title).name self._tab_id = 0 self._actor_toggle = build_checkbox( labels=[""], checked_labels=[""], on_change=self._toggle_actors ) self._opacity_label, self._opacity = build_slider( initial_value=1.0, max_value=1.0, text_template="{ratio:.0%}", on_change=self._change_opacity, label="Opacity", ) min_centers = self._actor.min_centers max_centers = self._actor.max_centers cross_section = self._actor.cross_section self._slice_x_label, self._slice_x = build_slider( initial_value=cross_section[0], min_value=min_centers[0], max_value=max_centers[0], text_template="{value:.0f}", label="X Slice", ) self._change_slice_x = partial(self._change_slice, selected_slice=self._slice_x) self._adjust_slice_x = partial(self._change_slice_x, sync_slice=True) self._slice_x.obj.on_moving_slider = self._change_slice_x self._slice_x.obj.on_value_changed = self._adjust_slice_x self._change_slice_visibility_x = partial( self._update_slice_visibility, selected_slice=self._slice_x ) self._slice_x_toggle = build_checkbox( labels=[""], checked_labels=[""], on_change=self._change_slice_visibility_x ) self._slice_y_label, self._slice_y = build_slider( initial_value=cross_section[1], min_value=min_centers[1], max_value=max_centers[1], text_template="{value:.0f}", label="Y Slice", ) self._change_slice_y = partial(self._change_slice, selected_slice=self._slice_y) self._adjust_slice_y = partial(self._change_slice_y, sync_slice=True) self._slice_y.obj.on_moving_slider = self._change_slice_y self._slice_y.obj.on_value_changed = self._adjust_slice_y self._change_slice_visibility_y = partial( self._update_slice_visibility, selected_slice=self._slice_y ) self._slice_y_toggle = build_checkbox( labels=[""], checked_labels=[""], on_change=self._change_slice_visibility_y ) self._slice_z_label, self._slice_z = build_slider( initial_value=cross_section[2], min_value=min_centers[2], max_value=max_centers[2], text_template="{value:.0f}", label="Z Slice", ) self._change_slice_z = partial(self._change_slice, selected_slice=self._slice_z) self._adjust_slice_z = partial(self._change_slice_z, sync_slice=True) self._slice_z.obj.on_moving_slider = self._change_slice_z self._slice_z.obj.on_value_changed = self._adjust_slice_z self._change_slice_visibility_z = partial( self._update_slice_visibility, selected_slice=self._slice_z ) self._slice_z_toggle = build_checkbox( labels=[""], checked_labels=[""], on_change=self._change_slice_visibility_z ) low_ranges = self._actor.low_ranges high_ranges = self._actor.high_ranges self._range_x_label, self._range_x = build_slider( initial_value=(low_ranges[0], high_ranges[0]), min_value=low_ranges[0], max_value=high_ranges[0], text_template="{value:.0f}", label="X Range", is_double_slider=True, ) self._change_range_x = partial(self._change_range, selected_range=self._range_x) self._range_x.obj.on_change = self._change_range_x self._range_y_label, self._range_y = build_slider( initial_value=(low_ranges[1], high_ranges[1]), min_value=low_ranges[1], max_value=high_ranges[1], text_template="{value:.0f}", label="Y Range", is_double_slider=True, ) self._change_range_y = partial(self._change_range, selected_range=self._range_y) self._range_y.obj.on_change = self._change_range_y self._range_z_label, self._range_z = build_slider( initial_value=(low_ranges[2], high_ranges[2]), min_value=low_ranges[2], max_value=high_ranges[2], text_template="{value:.0f}", label="Z Range", is_double_slider=True, ) self._change_range_z = partial(self._change_range, selected_range=self._range_z) self._range_z.obj.on_change = self._change_range_z self._view_mode_label = build_label(text="View Mode") self._view_modes = ["Cross section", "Range"] self._view_mode_toggler = build_radio_button( labels=self._view_modes, checked_labels=[self._view_modes[0]], padding=1.5, on_change=self._toggle_view_mode, ) self._file_label = build_label(text="Filename") self._file_name_label = build_label(text=self._file_name) self._register_elements( self._opacity_label, self._opacity, self._actor_toggle, self._slice_x_toggle, self._slice_x_label, self._slice_x, self._slice_y_toggle, self._slice_y_label, self._slice_y, self._slice_z_toggle, self._slice_z_label, self._slice_z, self._range_x_label, self._range_x, self._range_y_label, self._range_y, self._range_z_label, self._range_z, self._view_mode_label, self._view_mode_toggler, self._file_label, self._file_name_label, ) def _change_opacity(self, slider): """Update opacity of the peaks actor by adjusting the slider to suitable value. Parameters ---------- slider : LineSlider2D FURY slider UI element. """ self._actor.global_opacity = slider.value def _change_range(self, slider, selected_range): """Update the range of peaks actor by adjusting the double slider. Only usable in Range view mode. Parameters ---------- slider : LineDoubleSlider2D FURY two side slider UI element. selected_range : HorizonUIElement Selected horizon ui element intended to change. """ selected_range.selected_value = ( slider.left_disk_value, slider.right_disk_value, ) self._actor.display_extent( self._range_x.selected_value[0], self._range_x.selected_value[1], self._range_y.selected_value[0], self._range_y.selected_value[1], self._range_z.selected_value[0], self._range_z.selected_value[1], ) @warning_for_keywords() def _change_slice(self, slider, selected_slice, *, sync_slice=False): """Update the slice value of peaks actor by adjusting the slider. Only usable in Cross Section view mode. Parameters ---------- slider : LineSlider2D FURY slider UI element. selected_slice : HorizonUIElement Selected horizon ui element intended to change. sync_slice : bool, optional Whether the slice is getting synchronized some other change, by default False """ value = int(np.rint(slider.value)) selected_slice.selected_value = value if not sync_slice: self.on_slice_change( self._tab_id, self._slice_x.selected_value, self._slice_y.selected_value, self._slice_z.selected_value, ) if self._view_mode_toggler.selected_value[0] == self._view_modes[0]: visibility = [-1, -1, -1] self._slice_x.obj.set_visibility(self._slice_x.visibility) self._slice_y.obj.set_visibility(self._slice_y.visibility) self._slice_z.obj.set_visibility(self._slice_z.visibility) if self._slice_x.visibility: visibility[0] = self._slice_x.selected_value if self._slice_y.visibility: visibility[1] = self._slice_y.selected_value if self._slice_z.visibility: visibility[2] = self._slice_z.selected_value self._actor.display_cross_section( visibility[0], visibility[1], visibility[2], ) def _update_slice_visibility(self, checkboxes, selected_slice, *, visibility=None): if checkboxes is not None and "" in checkboxes.checked_labels: visibility = True elif visibility is None: visibility = False selected_slice.visibility = visibility selected_slice.obj.set_visibility(visibility) self._change_slice(selected_slice.obj, selected_slice, sync_slice=True) def _show_cross_section(self): """Show Cross Section view mode. Hide the Range sliders and labels.""" self.hide( self._range_x_label, self._range_x, self._range_y_label, self._range_y, self._range_z_label, self._range_z, ) self.show( self._slice_x_label, self._slice_x, self._slice_y_label, self._slice_y, self._slice_z_label, self._slice_z, ) self._change_slice(self._slice_x.obj, self._slice_x, sync_slice=True) def _show_range(self): """Show Range view mode. Hide Cross Section sliders and labels.""" self.hide( self._slice_x_label, self._slice_x, self._slice_y_label, self._slice_y, self._slice_z_label, self._slice_z, ) self.show( self._range_x_label, self._range_x, self._range_y_label, self._range_y, self._range_z_label, self._range_z, ) def _toggle_view_mode(self, radio): self._view_mode_toggler.selected_value = radio.checked_labels if radio.checked_labels[0] == self._view_modes[0]: self._actor.display_cross_section( self._actor.cross_section[0], self._actor.cross_section[1], self._actor.cross_section[2], ) self._show_cross_section() else: self._actor.display_extent( self._actor.low_ranges[0], self._actor.high_ranges[0], self._actor.low_ranges[1], self._actor.high_ranges[1], self._actor.low_ranges[2], self._actor.high_ranges[2], ) self._show_range()
[docs] def on_tab_selected(self): """Trigger when tab becomes active.""" super().on_tab_selected() self._toggle_view_mode(self._view_mode_toggler.obj)
[docs] def update_slices(self, x_slice, y_slice, z_slice): """Updates slicer positions. Parameters ---------- x_slice: float x-value where the slicer should be placed y_slice: float y-value where the slicer should be placed z_slice: float z-value where the slicer should be placed """ if not self._slice_x.obj.value == x_slice: self._slice_x.obj.value = x_slice if not self._slice_y.obj.value == y_slice: self._slice_y.obj.value = y_slice if not self._slice_z.obj.value == z_slice: self._slice_z.obj.value = z_slice
def _toggle_actors(self, checkbox): """Toggle the opacity of the peaks actor and slider. Parameters ---------- checkbox : CheckBox2D FURY checkbox UI element. """ if "" in checkbox.checked_labels: self.show(self._opacity.obj) else: self.hide(self._opacity.obj) super()._toggle_actors(checkbox)
[docs] def build(self, tab_id): """Build all the elements under the tab. Parameters ---------- tab_id : int Id of the tab. """ self._tab_id = tab_id x_pos = 0.02 self._actor_toggle.position = (x_pos, 0.85) self._slice_x_toggle.position = (x_pos, 0.62) self._slice_y_toggle.position = (x_pos, 0.38) self._slice_z_toggle.position = (x_pos, 0.15) x_pos = 0.04 self._opacity_label.position = (x_pos, 0.85) self._slice_x_label.position = (x_pos, 0.62) self._slice_y_label.position = (x_pos, 0.38) self._slice_z_label.position = (x_pos, 0.15) self._range_x_label.position = (x_pos, 0.62) self._range_y_label.position = (x_pos, 0.38) self._range_z_label.position = (x_pos, 0.15) x_pos = 0.10 self._opacity.position = (x_pos, 0.85) self._slice_x.position = (x_pos, 0.62) self._slice_y.position = (x_pos, 0.38) self._slice_z.position = (x_pos, 0.15) x_pos = 0.105 self._range_x.position = (x_pos, 0.66) self._range_y.position = (x_pos, 0.42) self._range_z.position = (x_pos, 0.19) x_pos = 0.52 self._view_mode_label.position = (x_pos, 0.85) self._file_label.position = (x_pos, 0.28) x_pos = 0.62 self._view_mode_toggler.position = (x_pos, 0.80) self._file_name_label.position = (x_pos, 0.28) if is_macOS: self._file_name_label.size = (800, "auto") else: self._file_name_label.size = (400, "auto") cross_section = self._actor.cross_section self._actor.display_cross_section( cross_section[0], cross_section[1], cross_section[2] )
@property def name(self): """Name of the tab. Returns ------- str """ return self._name @property def actors(self): """actors controlled by tab. Returns ------- list List of actors. """ return [self._actor]