Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Horizon Tabs #2744

Merged
merged 136 commits into from Apr 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
861e51a
Decoupled image slicer panel from peak panel.
guaje Feb 18, 2023
82d0b52
Decoupled peak from image slicer. Added pam validation. Added new pea…
guaje Feb 18, 2023
b179915
Added horizon module in viz module.
guaje Mar 8, 2023
cbf9173
Moved tab.py.
guaje Mar 8, 2023
48ff63d
Renamed tab.py as base.py. Added tab file for peak data.
guaje Mar 8, 2023
ff271fd
Renamed tabs module as tab.
guaje Mar 8, 2023
676fdc2
Added peaks tab functionality.
guaje Mar 8, 2023
65fc6a4
Added build function to handle initialization.
guaje Mar 9, 2023
d15cf70
Added classes reindexing at the tab module level.
guaje Mar 9, 2023
80fca7c
Refactored private functions. Refactored concrete methods in PeakTab …
guaje Mar 9, 2023
458d1fa
Added abstract HorizonTab class.
guaje Mar 9, 2023
fe59d15
Indexed HorizonTab class in tab module.
guaje Mar 9, 2023
6d02bfd
PeaksTab now inherits from HorizonTab.
guaje Mar 9, 2023
998c34b
Added tab_ui property and tabs initialization to TabManager.
guaje Mar 9, 2023
b0e8b12
Added tab manager to app.
guaje Mar 9, 2023
aedb9c4
Fixed abstract method and property conflict.
guaje Mar 9, 2023
df8afa7
Tab repositioning.
guaje Mar 9, 2023
7143cfd
Minor fixes in peak tab.
guaje Mar 9, 2023
da4e5d1
Added build_label utility function.
guaje Mar 13, 2023
bc11911
Added color_slider utility function.
guaje Mar 13, 2023
48bc2e9
Minor changes in utility functions.
guaje Mar 13, 2023
2df5e0f
Resized show manager. Forwarded window size to TabManager.
guaje Mar 14, 2023
552fec6
Computed tab size and position from window size.
guaje Mar 14, 2023
4025018
Added panel in PeakTab.
guaje Mar 16, 2023
5fe105c
Adjusted PeakTab's panel look and feel.
guaje Mar 16, 2023
ef03157
Added RoIsTab.
guaje Mar 16, 2023
b881904
Indexed RoIsTab.
guaje Mar 16, 2023
8b15cb9
Added RoIsTab to build_show function. Changed behavior of RoI contour…
guaje Mar 16, 2023
8f72baa
Removed unused import in roi.py.
guaje Mar 16, 2023
893849d
Minor aesthetic changes in RoIsTab.
guaje Mar 16, 2023
31671d0
Aesthetic changes on PeaksTab.
guaje Mar 16, 2023
3017b86
Minor changes in PeaksTab.
guaje Mar 16, 2023
382cb4a
Removed custom panel from PeaksTab to fix draggable issue.
guaje Mar 16, 2023
d217d89
Fixed minor issue on panel replacement in PeaksTab.
guaje Mar 16, 2023
b356ef1
Removed tab_size from build method in HorizonTab class.
guaje Mar 16, 2023
9cff5df
Removed panel from ROIs tab.
guaje Mar 20, 2023
0ca1b73
Renamed RoIsTab as ROIsTab.
guaje Mar 20, 2023
c449673
Changed look and feel of ROIs slider.
guaje Mar 20, 2023
4f29230
Changed ROIs tab label.
guaje Mar 20, 2023
ebee28b
Added SlicesTab with opacity, and x, y, z sliders.
guaje Mar 21, 2023
5887b17
Indexed SlicesTab class.
guaje Mar 21, 2023
57cb94e
Added nifti to actors function.
guaje Mar 21, 2023
d10075b
Added SlicesTab and nifti_to_actors to app.py
guaje Mar 21, 2023
b4f6fab
Fixed integer conversion in change slide events.
guaje Mar 21, 2023
2ab3ace
nifti loader renamed as slice.
guaje Mar 21, 2023
089d185
Aligned UI elements to left side of tab panel.
guaje Mar 21, 2023
cbdedcb
Renamed function color_slider to color_single_slider.
guaje Mar 21, 2023
6dac3bd
Added color_double_slider function.
guaje Mar 21, 2023
4308e3e
Changed sliders length and positions.
guaje Mar 21, 2023
a7af791
Forwarded additional data in nifti_to_slice_actors function.
guaje Mar 21, 2023
6348f7d
Forwarded nifti_to_slicer_actor data to SlicesTab.
guaje Mar 21, 2023
a54ef31
Commented access to TabUI properties.
guaje Mar 23, 2023
82bd4f4
Added event to change intensities.
guaje Mar 23, 2023
1caca43
Added colormap combobox.
guaje Mar 23, 2023
f082d8c
Added radio buttons to control peaks view modes.
guaje Mar 23, 2023
f030d81
Replaced combobox in SlicesTab.
guaje Mar 28, 2023
c7e1a46
Adjusted left sliders positions.
guaje Mar 29, 2023
e177ae3
Added visibility buttons in SlicesTab.
guaje Mar 29, 2023
bddbc2d
Changed slice loader function.
guaje Mar 30, 2023
6092cdd
Changed slicer loader function to support 4D volume changing.
guaje Mar 30, 2023
ccf8e74
Minor changes on SlicesTab.
guaje Mar 30, 2023
bd79554
Added icon list for visibility icons.
guaje Mar 30, 2023
54c860d
Removed combobox.
guaje Apr 3, 2023
d887b72
Adjusted output of add_slice_actors function.
guaje Apr 3, 2023
45dcfb5
Ajusted output of add_slice_actors function.
guaje Apr 3, 2023
298d0a1
Forwarded global memory to tabs.
guaje Apr 3, 2023
08ed718
Added change volume interaction.
guaje Apr 5, 2023
306de3b
Added SlicesLoader class to improve slices management.
guaje Apr 5, 2023
639ad08
Fixed volume limits.
guaje Apr 5, 2023
23851e3
Removed global memory parameter from tabs.
guaje Apr 5, 2023
fadf3cf
Removed unused stuff from global memory.
guaje Apr 5, 2023
0047869
Removed function to add slice actors.
guaje Apr 5, 2023
7668363
Minor adjustments in ROIsTab.
guaje Apr 5, 2023
4813124
Added change_volume function to SlicesLoader. Removed static function.
guaje Apr 6, 2023
7c2dea5
Minor changes in Global Memory.
guaje Apr 6, 2023
b1e8233
Added functionality to mantain slices visibility after changing volumes.
guaje Apr 6, 2023
c258a05
Added functionality to keep slices opacity after changing volumes.
guaje Apr 6, 2023
a103d68
Added slices pickers.
guaje Apr 6, 2023
668094b
Added label for picker
guaje Apr 6, 2023
aaa7e0f
Added temporary fix to add ClustersTab.
guaje Apr 6, 2023
c40df4e
Replaced slice references by slice_actor in Slices Tab and Loader.
guaje Apr 6, 2023
73b2b7d
Added startup_tab_id from FURY #778 to initialize tabs expanded.
guaje Apr 10, 2023
08193a6
Layout changes in SlicesTab.
guaje Apr 10, 2023
b3f0464
Reverted clusters fix.
guaje Apr 10, 2023
3adac79
Preparing to merge with clusters fix.
guaje Apr 10, 2023
c5001fd
Added SlicesTab __change_picked_voxel callback.
guaje Apr 10, 2023
34d3864
Added register_picker_callback to SlicesLoader.
guaje Apr 10, 2023
ec8824f
Added function to replace picked voxel actor.
guaje Apr 12, 2023
2177eff
Fixed clusters.
guaje Apr 12, 2023
70106b7
Removed slices panel from app.
guaje Apr 12, 2023
ec6ddeb
Added ClustersTab.
guaje Apr 12, 2023
5b4465b
Added ClustersTab.
guaje Apr 12, 2023
8d777d2
Added events to handle cluster size and length.
guaje Apr 12, 2023
3c96079
Added change of threshold event.
guaje Apr 12, 2023
f82ebc8
Preparing to merge
guaje Apr 12, 2023
cace4d1
Merge branch 'dipy-master' into horizon_tabs
guaje Apr 12, 2023
36f13a0
Discarded cluster functions from app. Repositioned help panel.
guaje Apr 14, 2023
fb0a312
Renamed loaders as visualizers.
guaje Apr 14, 2023
0b49087
Added ClusterVisualizer.
guaje Apr 18, 2023
f9b5e87
Merge branch 'dipy-master' into horizon_tabs
guaje Apr 18, 2023
4609555
Minor changes in SlicesVisualizer.
guaje Apr 19, 2023
74318b9
Refactored references to SlicesLoader.
guaje Apr 19, 2023
25f3016
Added first version of ClustersVisualizer.
guaje Apr 19, 2023
6bcc1a6
Merge branch 'dipy-master' into horizon_tabs
guaje Apr 19, 2023
a574170
Added add_cluster_actors function to ClustersVisualizer.
guaje Apr 19, 2023
6740f01
Passing ClustersVisualizer to ClustersTab.
guaje Apr 19, 2023
d0af368
Removed unused stuff from cluster panel.
guaje Apr 19, 2023
13a6c7c
Added recluster_tractograms function. Finished change_threshold event.
guaje Apr 20, 2023
23af5ac
Added update calls to slider_intensities.
guaje Apr 20, 2023
62770ce
Minor changes in ClustersVisualizer.
guaje Apr 20, 2023
137f0c8
Refactored key_press as a private class method. Refactored show_all a…
guaje Apr 20, 2023
6d01e30
Disabled picking feedback. Fix in another PR.
guaje Apr 20, 2023
d6e77d0
Fixed percentileofscore calculations.
guaje Apr 20, 2023
9bd2809
Added tractogram_clusters property to ClustersVisualizer.
guaje Apr 20, 2023
670df40
Fixed key_events show_all, expand, hide, invert, reset, and new_window.
guaje Apr 20, 2023
01372bd
Fixed save key_press event.
guaje Apr 20, 2023
5a1330f
Minor changes in Slices Tab and Visualizer.
guaje Apr 20, 2023
4c7d162
Added TabUI repositioning based on window size changes.
guaje Apr 20, 2023
57f3b54
Fixed help panel repositioning.
guaje Apr 20, 2023
95708b5
Improved key_press_event 'o', now it's a toggle button.
guaje Apr 20, 2023
65bc03c
Fixed show_all function.
guaje Apr 20, 2023
0f7e9dd
Fixed help panel repositioning based on status.
guaje Apr 20, 2023
05d67ea
Revised hide fucntion.
guaje Apr 20, 2023
86ee72e
Revised invert function.
guaje Apr 20, 2023
81cecee
Revised reset function.
guaje Apr 20, 2023
4317169
Added 'o' label in help menu.
guaje Apr 20, 2023
2897c16
Changed font size in tab bar items. Added space.
guaje Apr 20, 2023
cf75f25
Removed right click option from help menu.
guaje Apr 20, 2023
462bb2a
Added support for multiple images.
guaje Apr 21, 2023
3609df5
Added multi-image support with roi_images flag.
guaje Apr 21, 2023
af942af
Removed panel references.
guaje Apr 21, 2023
54d1c65
Merge branch 'dipy-master' into horizon_tabs
guaje Apr 21, 2023
641505f
Restored panel file.
guaje Apr 21, 2023
52e51f4
Moved app.py to horizon module.
guaje Apr 21, 2023
f12e49d
Added new horizon modules to setup.py
guaje Apr 21, 2023
c989a6c
Fixed roi_images test.
guaje Apr 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
943 changes: 0 additions & 943 deletions dipy/viz/app.py

This file was deleted.

4 changes: 0 additions & 4 deletions dipy/viz/gmem.py
Expand Up @@ -39,7 +39,3 @@ def __init__(self):
self.streamline_actors = []
self.centroid_actors = []
self.cluster_actors = []

# roi level sharing
self.roi_opacity = 1
self.slicer_roi_actor = []
Empty file added dipy/viz/horizon/__init__.py
Empty file.
685 changes: 685 additions & 0 deletions dipy/viz/horizon/app.py

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions dipy/viz/horizon/tab/__init__.py
@@ -0,0 +1,11 @@
from dipy.viz.horizon.tab.base import (HorizonTab, TabManager, build_label,
color_double_slider,
color_single_slider)
from dipy.viz.horizon.tab.cluster import ClustersTab
from dipy.viz.horizon.tab.peak import PeaksTab
from dipy.viz.horizon.tab.roi import ROIsTab
from dipy.viz.horizon.tab.slice import SlicesTab

__all__ = [
'HorizonTab', 'TabManager', 'ClustersTab', 'PeaksTab', 'ROIsTab',
'SlicesTab', 'build_label', 'color_double_slider', 'color_single_slider']
94 changes: 94 additions & 0 deletions dipy/viz/horizon/tab/base.py
@@ -0,0 +1,94 @@
from abc import ABC, abstractmethod

import numpy as np

from dipy.utils.optpkg import optional_package

fury, has_fury, setup_module = optional_package('fury')

if has_fury:
from fury import ui


class HorizonTab(ABC):
@abstractmethod
def build(self, tab_id, tab_ui):
pass

@property
@abstractmethod
def name(self):
pass

class TabManager:
def __init__(self, tabs, win_size):
num_tabs = len(tabs)
win_width, win_height = win_size

# TODO: Add dynamic sizing
# tab_size = (np.rint(win_width / 1.5), np.rint(win_height / 4.5))
self.__tab_size = (1280, 240)
x_pad = np.rint((win_width - self.__tab_size[0]) / 2)

self.__tab_ui = ui.TabUI(
position=(x_pad, 5), size=self.__tab_size, nb_tabs=num_tabs,
active_color=(1, 1, 1), inactive_color=(0.5, 0.5, 0.5),
draggable=True, startup_tab_id=0)

for id, tab in enumerate(tabs):
self.__tab_ui.tabs[id].title = ' ' + tab.name
self.__tab_ui.tabs[id].title_font_size = 18
tab.build(id, self.__tab_ui)

def reposition(self, win_size):
win_width, win_height = win_size
x_pad = np.rint((win_width - self.__tab_size[0]) / 2)
self.__tab_ui.position = (x_pad, 5)

@property
def tab_ui(self):
return self.__tab_ui


def build_label(text, font_size=16, bold=False):
"""
Simple utility function to build labels

Parameters
----------
text : str
font_size : int
bold : bool

Returns
-------
label : TextBlock2D
"""

label = ui.TextBlock2D()
label.message = text
label.font_size = font_size
label.font_family = 'Arial'
label.justification = 'left'
label.bold = bold
label.italic = False
label.shadow = False
label.actor.GetTextProperty().SetBackgroundColor(0, 0, 0)
label.actor.GetTextProperty().SetBackgroundOpacity(0.0)
label.color = (0.7, 0.7, 0.7)

return label


def color_single_slider(slider):
slider.default_color = (1., .5, .0)
slider.track.color = (.8, .3, .0)
slider.active_color = (.9, .4, .0)
slider.handle.color = (1., .5, .0)

def color_double_slider(slider):
slider.default_color = (1., .5, .0)
slider.track.color = (.8, .3, .0)
slider.active_color = (.9, .4, .0)
slider.handles[0].color = (1., .5, .0)
slider.handles[1].color = (1., .5, .0)
152 changes: 152 additions & 0 deletions dipy/viz/horizon/tab/cluster.py
@@ -0,0 +1,152 @@
import numpy as np

from dipy.utils.optpkg import optional_package
from dipy.viz.horizon.tab import HorizonTab, build_label, color_single_slider

fury, has_fury, setup_module = optional_package('fury')

if has_fury:
from fury import ui


class ClustersTab(HorizonTab):
def __init__(self, clusters_visualizer, threshold):

self.__visualizer = clusters_visualizer

self.__centroid_actors = self.__visualizer.centroid_actors
self.__cluster_actors = self.__visualizer.cluster_actors
self.__name = 'Clusters'

self.__tab_id = 0
self.__tab_ui = None

length = 450
lw = 3
radius = 8
fs = 16
tt = '{value:.0f}'

self.__slider_label_size = build_label(text='Size')

sizes = self.__visualizer.sizes
self.__selected_size = np.percentile(sizes, 50)

self.__slider_size = ui.LineSlider2D(
initial_value=self.__selected_size, min_value=np.min(sizes),
max_value=np.percentile(sizes, 98), length=length, line_width=lw,
outer_radius=radius, font_size=fs, text_template=tt)

color_single_slider(self.__slider_size)

self.__slider_size.handle_events(self.__slider_size.handle.actor)
self.__slider_size.on_left_mouse_button_released = self.__change_size

self.__slider_label_length = build_label(text='Length')

lengths = self.__visualizer.lengths
self.__selected_length = np.percentile(lengths, 25)

self.__slider_length = ui.LineSlider2D(
initial_value=self.__selected_length, min_value=np.min(lengths),
max_value=np.percentile(lengths, 98), length=length, line_width=lw,
outer_radius=radius, font_size=fs, text_template=tt)

color_single_slider(self.__slider_length)

self.__slider_length.handle_events(self.__slider_length.handle.actor)
self.__slider_length.on_left_mouse_button_released = (
self.__change_length)

self.__slider_label_threshold = build_label(text='Threshold')

self.__selected_threshold = threshold

self.__slider_threshold = ui.LineSlider2D(
initial_value=self.__selected_threshold, min_value=5, max_value=25,
length=length, line_width=lw, outer_radius=radius, font_size=fs,
text_template=tt)

color_single_slider(self.__slider_threshold)

self.__slider_threshold.handle_events(
self.__slider_threshold.handle.actor)
self.__slider_threshold.on_left_mouse_button_released = (
self.__change_threshold)

def __change_length(self, istyle, obj, slider):
self.__selected_length = int(np.rint(slider.value))
self.__update_clusters()
istyle.force_render()

def __change_size(self, istyle, obj, slider):
self.__selected_size = int(np.rint(slider.value))
self.__update_clusters()
istyle.force_render()

def __change_threshold(self, istyle, obj, slider):
value = int(np.rint(slider.value))
if value != self.__selected_threshold:
self.__visualizer.recluster_tractograms(value)

sizes = self.__visualizer.sizes
self.__selected_size = np.percentile(sizes, 50)

lengths = self.__visualizer.lengths
self.__selected_length = np.percentile(lengths, 25)

self.__update_clusters()

# Updating size slider
self.__slider_size.min_value = np.min(sizes)
self.__slider_size.max_value = np.percentile(sizes, 98)
self.__slider_size.value = self.__selected_size
self.__slider_size.update()

# Updating length slider
self.__slider_length.min_value = np.min(lengths)
self.__slider_length.max_value = np.percentile(lengths, 98)
self.__slider_length.value = self.__selected_length
self.__slider_length.update()

self.__selected_threshold = value
istyle.force_render()

def __update_clusters(self):
for k in self.__cluster_actors:
length_validation = (
self.__cluster_actors[k]['length'] < self.__selected_length)
size_validation = (
self.__cluster_actors[k]['size'] < self.__selected_size)
if (length_validation or size_validation):
self.__cluster_actors[k]['actor'].SetVisibility(False)
if k.GetVisibility():
k.SetVisibility(False)
else:
self.__cluster_actors[k]['actor'].SetVisibility(True)

def build(self, tab_id, tab_ui):
self.__tab_id = tab_id
self.__tab_ui = tab_ui

x_pos = .02

self.__tab_ui.add_element(
self.__tab_id, self.__slider_label_size, (x_pos, .85))
self.__tab_ui.add_element(
self.__tab_id, self.__slider_label_length, (x_pos, .62))
self.__tab_ui.add_element(
self.__tab_id, self.__slider_label_threshold, (x_pos, .38))

x_pos=.12

self.__tab_ui.add_element(
self.__tab_id, self.__slider_size, (x_pos, .85))
self.__tab_ui.add_element(
self.__tab_id, self.__slider_length, (x_pos, .62))
self.__tab_ui.add_element(
self.__tab_id, self.__slider_threshold, (x_pos, .38))

@property
def name(self):
return self.__name