Commit 894282fe02647efd0be97fbbbc14baa2b2afa1b3
1 parent
d4121f67
Exists in
measure
The ClutImagedata is changing the slice lookuptable
Showing
3 changed files
with
73 additions
and
10 deletions
Show diff stats
invesalius/data/slice_.py
@@ -34,6 +34,11 @@ import utils | @@ -34,6 +34,11 @@ import utils | ||
34 | from mask import Mask | 34 | from mask import Mask |
35 | from project import Project | 35 | from project import Project |
36 | 36 | ||
37 | +OTHER=0 | ||
38 | +PLIST=1 | ||
39 | +WIDGET=2 | ||
40 | + | ||
41 | + | ||
37 | class SliceBuffer(object): | 42 | class SliceBuffer(object): |
38 | """ | 43 | """ |
39 | This class is used as buffer that mantains the vtkImageData and numpy array | 44 | This class is used as buffer that mantains the vtkImageData and numpy array |
@@ -66,9 +71,6 @@ class SliceBuffer(object): | @@ -66,9 +71,6 @@ class SliceBuffer(object): | ||
66 | self.vtk_mask = None | 71 | self.vtk_mask = None |
67 | 72 | ||
68 | 73 | ||
69 | - | ||
70 | - | ||
71 | - | ||
72 | class Slice(object): | 74 | class Slice(object): |
73 | __metaclass__= utils.Singleton | 75 | __metaclass__= utils.Singleton |
74 | # Only one slice will be initialized per time (despite several viewers | 76 | # Only one slice will be initialized per time (despite several viewers |
@@ -94,8 +96,7 @@ class Slice(object): | @@ -94,8 +96,7 @@ class Slice(object): | ||
94 | self.num_gradient = 0 | 96 | self.num_gradient = 0 |
95 | self.interaction_style = st.StyleStateManager() | 97 | self.interaction_style = st.StyleStateManager() |
96 | 98 | ||
97 | - self.from_plist = False | ||
98 | - | 99 | + self.from_ = OTHER |
99 | self.__bind_events() | 100 | self.__bind_events() |
100 | 101 | ||
101 | def __bind_events(self): | 102 | def __bind_events(self): |
@@ -130,6 +131,9 @@ class Slice(object): | @@ -130,6 +131,9 @@ class Slice(object): | ||
130 | Publisher.subscribe(self.UpdateColourTableBackgroundPlist,\ | 131 | Publisher.subscribe(self.UpdateColourTableBackgroundPlist,\ |
131 | 'Change colour table from background image from plist') | 132 | 'Change colour table from background image from plist') |
132 | 133 | ||
134 | + Publisher.subscribe(self.UpdateColourTableBackgroundWidget,\ | ||
135 | + 'Change colour table from background image from widget') | ||
136 | + | ||
133 | Publisher.subscribe(self.InputImageWidget, 'Input Image in the widget') | 137 | Publisher.subscribe(self.InputImageWidget, 'Input Image in the widget') |
134 | 138 | ||
135 | Publisher.subscribe(self.OnExportMask,'Export mask to file') | 139 | Publisher.subscribe(self.OnExportMask,'Export mask to file') |
@@ -707,7 +711,7 @@ class Slice(object): | @@ -707,7 +711,7 @@ class Slice(object): | ||
707 | 711 | ||
708 | def UpdateColourTableBackground(self, pubsub_evt): | 712 | def UpdateColourTableBackground(self, pubsub_evt): |
709 | values = pubsub_evt.data | 713 | values = pubsub_evt.data |
710 | - self.from_plist = False | 714 | + self.from_= OTHER |
711 | self.number_of_colours= values[0] | 715 | self.number_of_colours= values[0] |
712 | self.saturation_range = values[1] | 716 | self.saturation_range = values[1] |
713 | self.hue_range = values[2] | 717 | self.hue_range = values[2] |
@@ -718,7 +722,14 @@ class Slice(object): | @@ -718,7 +722,14 @@ class Slice(object): | ||
718 | 722 | ||
719 | def UpdateColourTableBackgroundPlist(self, pubsub_evt): | 723 | def UpdateColourTableBackgroundPlist(self, pubsub_evt): |
720 | self.values = pubsub_evt.data | 724 | self.values = pubsub_evt.data |
721 | - self.from_plist = True | 725 | + self.from_= PLIST |
726 | + for buffer_ in self.buffer_slices.values(): | ||
727 | + buffer_.discard_vtk_image() | ||
728 | + Publisher.sendMessage('Reload actual slice') | ||
729 | + | ||
730 | + def UpdateColourTableBackgroundWidget(self, pubsub_evt): | ||
731 | + self.values = pubsub_evt.data | ||
732 | + self.from_= WIDGET | ||
722 | for buffer_ in self.buffer_slices.values(): | 733 | for buffer_ in self.buffer_slices.values(): |
723 | buffer_.discard_vtk_image() | 734 | buffer_.discard_vtk_image() |
724 | Publisher.sendMessage('Reload actual slice') | 735 | Publisher.sendMessage('Reload actual slice') |
@@ -829,7 +840,7 @@ class Slice(object): | @@ -829,7 +840,7 @@ class Slice(object): | ||
829 | Publisher.sendMessage('Update slice viewer') | 840 | Publisher.sendMessage('Update slice viewer') |
830 | 841 | ||
831 | def do_ww_wl(self, image): | 842 | def do_ww_wl(self, image): |
832 | - if self.from_plist: | 843 | + if self.from_ == PLIST: |
833 | lut = vtk.vtkWindowLevelLookupTable() | 844 | lut = vtk.vtkWindowLevelLookupTable() |
834 | lut.SetWindow(self.window_width) | 845 | lut.SetWindow(self.window_width) |
835 | lut.SetLevel(self.window_level) | 846 | lut.SetLevel(self.window_level) |
@@ -847,6 +858,20 @@ class Slice(object): | @@ -847,6 +858,20 @@ class Slice(object): | ||
847 | colorer.SetLookupTable(lut) | 858 | colorer.SetLookupTable(lut) |
848 | colorer.SetOutputFormatToRGB() | 859 | colorer.SetOutputFormatToRGB() |
849 | colorer.Update() | 860 | colorer.Update() |
861 | + elif self.from_ == WIDGET: | ||
862 | + lut = vtk.vtkColorTransferFunction() | ||
863 | + | ||
864 | + for n in self.values: | ||
865 | + r, g, b = n.colour | ||
866 | + lut.AddRGBPoint(n.value, r/255.0, g/255.0, b/255.0) | ||
867 | + | ||
868 | + lut.Build() | ||
869 | + | ||
870 | + colorer = vtk.vtkImageMapToColors() | ||
871 | + colorer.SetLookupTable(lut) | ||
872 | + colorer.SetInput(image) | ||
873 | + colorer.SetOutputFormatToRGB() | ||
874 | + colorer.Update() | ||
850 | else: | 875 | else: |
851 | colorer = vtk.vtkImageMapToWindowLevelColors() | 876 | colorer = vtk.vtkImageMapToWindowLevelColors() |
852 | colorer.SetInput(image) | 877 | colorer.SetInput(image) |
@@ -869,7 +894,7 @@ class Slice(object): | @@ -869,7 +894,7 @@ class Slice(object): | ||
869 | return m.astype('uint8') | 894 | return m.astype('uint8') |
870 | 895 | ||
871 | def do_colour_image(self, imagedata): | 896 | def do_colour_image(self, imagedata): |
872 | - if self.from_plist: | 897 | + if self.from_ in (PLIST, WIDGET): |
873 | return imagedata | 898 | return imagedata |
874 | else: | 899 | else: |
875 | # map scalar values into colors | 900 | # map scalar values into colors |
invesalius/gui/dialogs.py
@@ -34,6 +34,9 @@ import project as proj | @@ -34,6 +34,9 @@ import project as proj | ||
34 | import session as ses | 34 | import session as ses |
35 | import utils | 35 | import utils |
36 | 36 | ||
37 | +from gui.widgets import clut_imagedata | ||
38 | + | ||
39 | +import numpy as np | ||
37 | 40 | ||
38 | class MaskEvent(wx.PyCommandEvent): | 41 | class MaskEvent(wx.PyCommandEvent): |
39 | def __init__(self , evtType, id, mask_index): | 42 | def __init__(self , evtType, id, mask_index): |
@@ -1274,9 +1277,32 @@ class SurfaceMethodPanel(wx.Panel): | @@ -1274,9 +1277,32 @@ class SurfaceMethodPanel(wx.Panel): | ||
1274 | self.method_sizer.Layout() | 1277 | self.method_sizer.Layout() |
1275 | 1278 | ||
1276 | 1279 | ||
1280 | +class ClutImagedataDialog(wx.Dialog): | ||
1281 | + def __init__(self): | ||
1282 | + pre = wx.PreDialog() | ||
1283 | + pre.Create(None, -1, style=wx.DEFAULT_DIALOG_STYLE) | ||
1284 | + self.PostCreate(pre) | ||
1277 | 1285 | ||
1286 | + self._init_gui() | ||
1287 | + self._bind_events_wx() | ||
1278 | 1288 | ||
1279 | - | 1289 | + def _init_gui(self): |
1290 | + self.clut_widget = clut_imagedata.CLUTImageDataWidget(self, -1, | ||
1291 | + np.random.randint(0, | ||
1292 | + 1000, | ||
1293 | + (1000,)), | ||
1294 | + -1000, 1000, | ||
1295 | + 230, 255) | ||
1296 | + sizer = wx.BoxSizer(wx.VERTICAL) | ||
1297 | + sizer.Add(self.clut_widget, 1, wx.EXPAND) | ||
1298 | + | ||
1299 | + self.SetSizer(sizer) | ||
1300 | + self.Fit() | ||
1280 | 1301 | ||
1302 | + def _bind_events_wx(self): | ||
1303 | + self.clut_widget.Bind(clut_imagedata.EVT_CLUT_POINT_MOVE, self.OnClutChange) | ||
1281 | 1304 | ||
1305 | + def OnClutChange(self, evt): | ||
1306 | + Publisher.sendMessage('Change colour table from background image from widget', | ||
1307 | + evt.GetNodes()) | ||
1282 | 1308 |
invesalius/gui/widgets/slice_menu.py
@@ -26,6 +26,8 @@ from wx.lib.pubsub import pub as Publisher | @@ -26,6 +26,8 @@ from wx.lib.pubsub import pub as Publisher | ||
26 | import constants as const | 26 | import constants as const |
27 | import presets | 27 | import presets |
28 | 28 | ||
29 | +from gui.dialogs import ClutImagedataDialog | ||
30 | + | ||
29 | class SliceMenu(wx.Menu): | 31 | class SliceMenu(wx.Menu): |
30 | def __init__(self): | 32 | def __init__(self): |
31 | wx.Menu.__init__(self) | 33 | wx.Menu.__init__(self) |
@@ -93,6 +95,11 @@ class SliceMenu(wx.Menu): | @@ -93,6 +95,11 @@ class SliceMenu(wx.Menu): | ||
93 | color_item = wx.MenuItem(submenu_wl, new_id, name, kind=wx.ITEM_RADIO) | 95 | color_item = wx.MenuItem(submenu_wl, new_id, name, kind=wx.ITEM_RADIO) |
94 | submenu_pseudo_colours.AppendItem(color_item) | 96 | submenu_pseudo_colours.AppendItem(color_item) |
95 | self.ID_TO_TOOL_ITEM[new_id] = color_item | 97 | self.ID_TO_TOOL_ITEM[new_id] = color_item |
98 | + | ||
99 | + new_id = wx.NewId() | ||
100 | + color_item = wx.MenuItem(submenu_wl, new_id, _('Custom'), kind=wx.ITEM_RADIO) | ||
101 | + submenu_pseudo_colours.AppendItem(color_item) | ||
102 | + self.ID_TO_TOOL_ITEM[new_id] = color_item | ||
96 | 103 | ||
97 | flag_tiling = False | 104 | flag_tiling = False |
98 | #------------ Sub menu of the image tiling --------------- | 105 | #------------ Sub menu of the image tiling --------------- |
@@ -180,5 +187,10 @@ class SliceMenu(wx.Menu): | @@ -180,5 +187,10 @@ class SliceMenu(wx.Menu): | ||
180 | Publisher.sendMessage('Set slice viewer layout', values) | 187 | Publisher.sendMessage('Set slice viewer layout', values) |
181 | Publisher.sendMessage('Update slice viewer') | 188 | Publisher.sendMessage('Update slice viewer') |
182 | 189 | ||
190 | + elif key == _('Custom'): | ||
191 | + cdialog = ClutImagedataDialog() | ||
192 | + cdialog.Show() | ||
193 | + | ||
194 | + | ||
183 | evt.Skip() | 195 | evt.Skip() |
184 | 196 |