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 | 34 | from mask import Mask |
35 | 35 | from project import Project |
36 | 36 | |
37 | +OTHER=0 | |
38 | +PLIST=1 | |
39 | +WIDGET=2 | |
40 | + | |
41 | + | |
37 | 42 | class SliceBuffer(object): |
38 | 43 | """ |
39 | 44 | This class is used as buffer that mantains the vtkImageData and numpy array |
... | ... | @@ -66,9 +71,6 @@ class SliceBuffer(object): |
66 | 71 | self.vtk_mask = None |
67 | 72 | |
68 | 73 | |
69 | - | |
70 | - | |
71 | - | |
72 | 74 | class Slice(object): |
73 | 75 | __metaclass__= utils.Singleton |
74 | 76 | # Only one slice will be initialized per time (despite several viewers |
... | ... | @@ -94,8 +96,7 @@ class Slice(object): |
94 | 96 | self.num_gradient = 0 |
95 | 97 | self.interaction_style = st.StyleStateManager() |
96 | 98 | |
97 | - self.from_plist = False | |
98 | - | |
99 | + self.from_ = OTHER | |
99 | 100 | self.__bind_events() |
100 | 101 | |
101 | 102 | def __bind_events(self): |
... | ... | @@ -130,6 +131,9 @@ class Slice(object): |
130 | 131 | Publisher.subscribe(self.UpdateColourTableBackgroundPlist,\ |
131 | 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 | 137 | Publisher.subscribe(self.InputImageWidget, 'Input Image in the widget') |
134 | 138 | |
135 | 139 | Publisher.subscribe(self.OnExportMask,'Export mask to file') |
... | ... | @@ -707,7 +711,7 @@ class Slice(object): |
707 | 711 | |
708 | 712 | def UpdateColourTableBackground(self, pubsub_evt): |
709 | 713 | values = pubsub_evt.data |
710 | - self.from_plist = False | |
714 | + self.from_= OTHER | |
711 | 715 | self.number_of_colours= values[0] |
712 | 716 | self.saturation_range = values[1] |
713 | 717 | self.hue_range = values[2] |
... | ... | @@ -718,7 +722,14 @@ class Slice(object): |
718 | 722 | |
719 | 723 | def UpdateColourTableBackgroundPlist(self, pubsub_evt): |
720 | 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 | 733 | for buffer_ in self.buffer_slices.values(): |
723 | 734 | buffer_.discard_vtk_image() |
724 | 735 | Publisher.sendMessage('Reload actual slice') |
... | ... | @@ -829,7 +840,7 @@ class Slice(object): |
829 | 840 | Publisher.sendMessage('Update slice viewer') |
830 | 841 | |
831 | 842 | def do_ww_wl(self, image): |
832 | - if self.from_plist: | |
843 | + if self.from_ == PLIST: | |
833 | 844 | lut = vtk.vtkWindowLevelLookupTable() |
834 | 845 | lut.SetWindow(self.window_width) |
835 | 846 | lut.SetLevel(self.window_level) |
... | ... | @@ -847,6 +858,20 @@ class Slice(object): |
847 | 858 | colorer.SetLookupTable(lut) |
848 | 859 | colorer.SetOutputFormatToRGB() |
849 | 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 | 875 | else: |
851 | 876 | colorer = vtk.vtkImageMapToWindowLevelColors() |
852 | 877 | colorer.SetInput(image) |
... | ... | @@ -869,7 +894,7 @@ class Slice(object): |
869 | 894 | return m.astype('uint8') |
870 | 895 | |
871 | 896 | def do_colour_image(self, imagedata): |
872 | - if self.from_plist: | |
897 | + if self.from_ in (PLIST, WIDGET): | |
873 | 898 | return imagedata |
874 | 899 | else: |
875 | 900 | # map scalar values into colors | ... | ... |
invesalius/gui/dialogs.py
... | ... | @@ -34,6 +34,9 @@ import project as proj |
34 | 34 | import session as ses |
35 | 35 | import utils |
36 | 36 | |
37 | +from gui.widgets import clut_imagedata | |
38 | + | |
39 | +import numpy as np | |
37 | 40 | |
38 | 41 | class MaskEvent(wx.PyCommandEvent): |
39 | 42 | def __init__(self , evtType, id, mask_index): |
... | ... | @@ -1274,9 +1277,32 @@ class SurfaceMethodPanel(wx.Panel): |
1274 | 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 | 26 | import constants as const |
27 | 27 | import presets |
28 | 28 | |
29 | +from gui.dialogs import ClutImagedataDialog | |
30 | + | |
29 | 31 | class SliceMenu(wx.Menu): |
30 | 32 | def __init__(self): |
31 | 33 | wx.Menu.__init__(self) |
... | ... | @@ -93,6 +95,11 @@ class SliceMenu(wx.Menu): |
93 | 95 | color_item = wx.MenuItem(submenu_wl, new_id, name, kind=wx.ITEM_RADIO) |
94 | 96 | submenu_pseudo_colours.AppendItem(color_item) |
95 | 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 | 104 | flag_tiling = False |
98 | 105 | #------------ Sub menu of the image tiling --------------- |
... | ... | @@ -180,5 +187,10 @@ class SliceMenu(wx.Menu): |
180 | 187 | Publisher.sendMessage('Set slice viewer layout', values) |
181 | 188 | Publisher.sendMessage('Update slice viewer') |
182 | 189 | |
190 | + elif key == _('Custom'): | |
191 | + cdialog = ClutImagedataDialog() | |
192 | + cdialog.Show() | |
193 | + | |
194 | + | |
183 | 195 | evt.Skip() |
184 | 196 | ... | ... |