Commit ad7294a7bb361541c7b081ad3a121a56eff25e79

Authored by Paulo Henrique Junqueira Amorim
Committed by GitHub
1 parent 2c9f1dc3

Added interpolated slice option

* ADD: Added slice interpolation optioni into menubar

* ADD: Added slice interpolation optioni into menubar

* ADD: Added interpolation into preferences
invesalius/constants.py
@@ -453,7 +453,7 @@ VTK_WARNING = 0 @@ -453,7 +453,7 @@ VTK_WARNING = 0
453 [ID_DICOM_IMPORT, ID_PROJECT_OPEN, ID_PROJECT_SAVE_AS, ID_PROJECT_SAVE, 453 [ID_DICOM_IMPORT, ID_PROJECT_OPEN, ID_PROJECT_SAVE_AS, ID_PROJECT_SAVE,
454 ID_PROJECT_CLOSE, ID_PROJECT_INFO, ID_SAVE_SCREENSHOT, ID_DICOM_LOAD_NET, 454 ID_PROJECT_CLOSE, ID_PROJECT_INFO, ID_SAVE_SCREENSHOT, ID_DICOM_LOAD_NET,
455 ID_PRINT_SCREENSHOT, ID_IMPORT_OTHERS_FILES, ID_ANALYZE_IMPORT, ID_PREFERENCES, 455 ID_PRINT_SCREENSHOT, ID_IMPORT_OTHERS_FILES, ID_ANALYZE_IMPORT, ID_PREFERENCES,
456 -ID_DICOM_NETWORK, ID_TIFF_JPG_PNG] = [wx.NewId() for number in range(14)] 456 +ID_DICOM_NETWORK, ID_TIFF_JPG_PNG, ID_VIEW_INTERPOLATED] = [wx.NewId() for number in range(15)]
457 ID_EXIT = wx.ID_EXIT 457 ID_EXIT = wx.ID_EXIT
458 ID_ABOUT = wx.ID_ABOUT 458 ID_ABOUT = wx.ID_ABOUT
459 459
@@ -549,7 +549,7 @@ STYLE_LEVEL = {SLICE_STATE_EDITOR: 1, @@ -549,7 +549,7 @@ STYLE_LEVEL = {SLICE_STATE_EDITOR: 1,
549 RENDERING = 0 549 RENDERING = 0
550 SURFACE_INTERPOLATION = 1 550 SURFACE_INTERPOLATION = 1
551 LANGUAGE = 2 551 LANGUAGE = 2
552 - 552 +SLICE_INTERPOLATION = 3
553 553
554 #Correlaction extracted from pyDicom 554 #Correlaction extracted from pyDicom
555 DICOM_ENCODING_TO_PYTHON = { 555 DICOM_ENCODING_TO_PYTHON = {
invesalius/data/viewer_slice.py
@@ -45,7 +45,7 @@ import data.vtk_utils as vtku @@ -45,7 +45,7 @@ import data.vtk_utils as vtku
45 import project 45 import project
46 import slice_data as sd 46 import slice_data as sd
47 import utils 47 import utils
48 - 48 +import session as ses
49 from data import converters 49 from data import converters
50 50
51 from data import measures 51 from data import measures
@@ -525,6 +525,10 @@ class Viewer(wx.Panel): @@ -525,6 +525,10 @@ class Viewer(wx.Panel):
525 # All renderers and image actors in this viewer 525 # All renderers and image actors in this viewer
526 self.slice_data_list = [] 526 self.slice_data_list = []
527 self.slice_data = None 527 self.slice_data = None
  528 +
  529 + self.slice_actor = None
  530 + self.interpolation_slice_status = True
  531 +
528 # The layout from slice_data, the first is number of cols, the second 532 # The layout from slice_data, the first is number of cols, the second
529 # is the number of rows 533 # is the number of rows
530 self.layout = (1, 1) 534 self.layout = (1, 1)
@@ -1085,6 +1089,8 @@ class Viewer(wx.Panel): @@ -1085,6 +1089,8 @@ class Viewer(wx.Panel):
1085 Publisher.subscribe(self.OnSetOverwriteMask, "Set overwrite mask") 1089 Publisher.subscribe(self.OnSetOverwriteMask, "Set overwrite mask")
1086 1090
1087 Publisher.subscribe(self.RefreshViewer, "Refresh viewer") 1091 Publisher.subscribe(self.RefreshViewer, "Refresh viewer")
  1092 + Publisher.subscribe(self.SetInterpolatedSlices, "Set interpolated slices")
  1093 + Publisher.subscribe(self.UpdateInterpolatedSlice, "Update Slice Interpolation")
1088 1094
1089 1095
1090 def RefreshViewer(self, pubsub_evt): 1096 def RefreshViewer(self, pubsub_evt):
@@ -1342,9 +1348,15 @@ class Viewer(wx.Panel): @@ -1342,9 +1348,15 @@ class Viewer(wx.Panel):
1342 self.interactor.GetRenderWindow().AddRenderer(renderer) 1348 self.interactor.GetRenderWindow().AddRenderer(renderer)
1343 1349
1344 actor = vtk.vtkImageActor() 1350 actor = vtk.vtkImageActor()
  1351 + self.slice_actor = actor
1345 # TODO: Create a option to let the user set if he wants to interpolate 1352 # TODO: Create a option to let the user set if he wants to interpolate
1346 # the slice images. 1353 # the slice images.
1347 - actor.InterpolateOff() 1354 +
  1355 + if int(ses.Session().slice_interpolation) == 1:
  1356 + actor.InterpolateOff()
  1357 + else:
  1358 + actor.InterpolateOn()
  1359 +
1348 slice_data = sd.SliceData() 1360 slice_data = sd.SliceData()
1349 slice_data.SetOrientation(self.orientation) 1361 slice_data.SetOrientation(self.orientation)
1350 slice_data.renderer = renderer 1362 slice_data.renderer = renderer
@@ -1358,6 +1370,26 @@ class Viewer(wx.Panel): @@ -1358,6 +1370,26 @@ class Viewer(wx.Panel):
1358 1370
1359 return slice_data 1371 return slice_data
1360 1372
  1373 + def UpdateInterpolatedSlice(self, pub_sub):
  1374 + if self.slice_actor != None:
  1375 + if ses.Session().slice_interpolation:
  1376 + self.slice_actor.InterpolateOff()
  1377 + else:
  1378 + self.slice_actor.InterpolateOn()
  1379 + self.interactor.Render()
  1380 +
  1381 +
  1382 + def SetInterpolatedSlices(self, pub_sub):
  1383 + self.interpolation_slice_status = status = pub_sub.data
  1384 +
  1385 + if self.slice_actor != None:
  1386 + if status == True:
  1387 + self.slice_actor.InterpolateOn()
  1388 + else:
  1389 + self.slice_actor.InterpolateOff()
  1390 +
  1391 + self.interactor.Render()
  1392 +
1361 def __update_camera(self): 1393 def __update_camera(self):
1362 orientation = self.orientation 1394 orientation = self.orientation
1363 proj = project.Project() 1395 proj = project.Project()
invesalius/gui/frame.py
@@ -85,6 +85,7 @@ class Frame(wx.Frame): @@ -85,6 +85,7 @@ class Frame(wx.Frame):
85 85
86 self.mw = None 86 self.mw = None
87 87
  88 +
88 if sys.platform != 'darwin': 89 if sys.platform != 'darwin':
89 self.Maximize() 90 self.Maximize()
90 91
@@ -95,8 +96,13 @@ class Frame(wx.Frame): @@ -95,8 +96,13 @@ class Frame(wx.Frame):
95 #self.SetSize(wx.Size(1024, 748)) 96 #self.SetSize(wx.Size(1024, 748))
96 97
97 98
  99 + #to control check and unckeck of menu view -> interpolated_slices
  100 + main_menu = MenuBar(self)
  101 +
  102 + self.actived_interpolated_slices = main_menu.view_menu
  103 +
98 # Set menus, status and task bar 104 # Set menus, status and task bar
99 - self.SetMenuBar(MenuBar(self)) 105 + self.SetMenuBar(main_menu)
100 self.SetStatusBar(StatusBar(self)) 106 self.SetStatusBar(StatusBar(self))
101 107
102 # Set TaskBarIcon 108 # Set TaskBarIcon
@@ -445,6 +451,20 @@ class Frame(wx.Frame): @@ -445,6 +451,20 @@ class Frame(wx.Frame):
445 elif id == const.ID_REMOVE_MASK_PART: 451 elif id == const.ID_REMOVE_MASK_PART:
446 self.OnRemoveMaskParts() 452 self.OnRemoveMaskParts()
447 453
  454 + elif id == const.ID_VIEW_INTERPOLATED:
  455 +
  456 + st = self.actived_interpolated_slices.IsChecked(const.ID_VIEW_INTERPOLATED)
  457 +
  458 + if st:
  459 + self.OnInterpolatedSlices(True)
  460 + else:
  461 + self.OnInterpolatedSlices(False)
  462 +
  463 + def OnInterpolatedSlices(self, status):
  464 +
  465 + Publisher.sendMessage('Set interpolated slices', status)
  466 +
  467 +
448 def OnSize(self, evt): 468 def OnSize(self, evt):
449 """ 469 """
450 Refresh GUI when frame is resized. 470 Refresh GUI when frame is resized.
@@ -478,9 +498,12 @@ class Frame(wx.Frame): @@ -478,9 +498,12 @@ class Frame(wx.Frame):
478 ses.Session().rendering = values[const.RENDERING] 498 ses.Session().rendering = values[const.RENDERING]
479 ses.Session().surface_interpolation = values[const.SURFACE_INTERPOLATION] 499 ses.Session().surface_interpolation = values[const.SURFACE_INTERPOLATION]
480 ses.Session().language = values[const.LANGUAGE] 500 ses.Session().language = values[const.LANGUAGE]
  501 + ses.Session().slice_interpolation = values[const.SLICE_INTERPOLATION]
481 502
482 Publisher.sendMessage('Remove Volume') 503 Publisher.sendMessage('Remove Volume')
483 Publisher.sendMessage('Reset Reaycasting') 504 Publisher.sendMessage('Reset Reaycasting')
  505 + Publisher.sendMessage('Update Slice Interpolation')
  506 + Publisher.sendMessage('Update Slice Interpolation MenuBar')
484 Publisher.sendMessage('Update Surface Interpolation') 507 Publisher.sendMessage('Update Surface Interpolation')
485 508
486 def ShowAbout(self): 509 def ShowAbout(self):
@@ -614,6 +637,7 @@ class MenuBar(wx.MenuBar): @@ -614,6 +637,7 @@ class MenuBar(wx.MenuBar):
614 sub(self.OnAddMask, "Add mask") 637 sub(self.OnAddMask, "Add mask")
615 sub(self.OnRemoveMasks, "Remove masks") 638 sub(self.OnRemoveMasks, "Remove masks")
616 sub(self.OnShowMask, "Show mask") 639 sub(self.OnShowMask, "Show mask")
  640 + sub(self.OnUpdateSliceInterpolation, "Update Slice Interpolation MenuBar")
617 641
618 self.num_masks = 0 642 self.num_masks = 0
619 643
@@ -718,7 +742,19 @@ class MenuBar(wx.MenuBar): @@ -718,7 +742,19 @@ class MenuBar(wx.MenuBar):
718 tools_menu.AppendMenu(-1, _(u'Image'), image_menu) 742 tools_menu.AppendMenu(-1, _(u'Image'), image_menu)
719 743
720 744
721 - # VIEW 745 + #View
  746 +
  747 + self.view_menu = view_menu = wx.Menu()
  748 + view_menu.Append(const.ID_VIEW_INTERPOLATED, _(u'Interpolated slices'), "", wx.ITEM_CHECK)
  749 +
  750 +
  751 + v = self.SliceInterpolationStatus()
  752 + self.view_menu.Check(const.ID_VIEW_INTERPOLATED, v)
  753 +
  754 + self.actived_interpolated_slices = self.view_menu
  755 +
  756 +
  757 +
722 #view_tool_menu = wx.Menu() 758 #view_tool_menu = wx.Menu()
723 #app = view_tool_menu.Append 759 #app = view_tool_menu.Append
724 #app(const.ID_TOOL_PROJECT, "Project Toolbar") 760 #app(const.ID_TOOL_PROJECT, "Project Toolbar")
@@ -765,12 +801,29 @@ class MenuBar(wx.MenuBar): @@ -765,12 +801,29 @@ class MenuBar(wx.MenuBar):
765 # Add all menus to menubar 801 # Add all menus to menubar
766 self.Append(file_menu, _("File")) 802 self.Append(file_menu, _("File"))
767 self.Append(file_edit, _("Edit")) 803 self.Append(file_edit, _("Edit"))
  804 + self.Append(view_menu, _(u"View"))
768 self.Append(tools_menu, _(u"Tools")) 805 self.Append(tools_menu, _(u"Tools"))
769 - #self.Append(view_menu, "View")  
770 #self.Append(tools_menu, "Tools") 806 #self.Append(tools_menu, "Tools")
771 self.Append(options_menu, _("Options")) 807 self.Append(options_menu, _("Options"))
772 self.Append(help_menu, _("Help")) 808 self.Append(help_menu, _("Help"))
773 809
  810 +
  811 + def SliceInterpolationStatus(self):
  812 +
  813 + status = int(ses.Session().slice_interpolation)
  814 +
  815 + if status == 0:
  816 + v = True
  817 + else:
  818 + v = False
  819 +
  820 + return v
  821 +
  822 + def OnUpdateSliceInterpolation(self, pubsub_evt):
  823 + v = self.SliceInterpolationStatus()
  824 + self.view_menu.Check(const.ID_VIEW_INTERPOLATED, v)
  825 +
  826 +
774 def OnEnableState(self, pubsub_evt): 827 def OnEnableState(self, pubsub_evt):
775 """ 828 """
776 Based on given state, enables or disables menu items which 829 Based on given state, enables or disables menu items which
invesalius/gui/preferences.py
@@ -26,7 +26,7 @@ class Preferences(wx.Dialog): @@ -26,7 +26,7 @@ class Preferences(wx.Dialog):
26 26
27 sizer = wx.BoxSizer(wx.VERTICAL) 27 sizer = wx.BoxSizer(wx.VERTICAL)
28 28
29 - bookStyle = fnb.FNB_NODRAG | fnb.FNB_NO_NAV_BUTTONS | fnb.FNB_NO_X_BUTTON 29 + bookStyle = fnb.FNB_NODRAG | fnb.FNB_NO_X_BUTTON
30 30
31 if AGW: 31 if AGW:
32 self.book = fnb.FlatNotebook(self, wx.ID_ANY, agwStyle=bookStyle) 32 self.book = fnb.FlatNotebook(self, wx.ID_ANY, agwStyle=bookStyle)
@@ -35,10 +35,12 @@ class Preferences(wx.Dialog): @@ -35,10 +35,12 @@ class Preferences(wx.Dialog):
35 35
36 sizer.Add(self.book, 80, wx.EXPAND|wx.ALL) 36 sizer.Add(self.book, 80, wx.EXPAND|wx.ALL)
37 37
  38 + self.pnl_viewer2d = Viewer2D(self)
38 self.pnl_viewer3d = Viewer3D(self) 39 self.pnl_viewer3d = Viewer3D(self)
39 self.pnl_language = Language(self) 40 self.pnl_language = Language(self)
40 41
41 - self.book.AddPage(self.pnl_viewer3d, _("Visualization")) 42 + self.book.AddPage(self.pnl_viewer2d, _("2D Visualization"))
  43 + self.book.AddPage(self.pnl_viewer3d, _("3D Visualization"))
42 self.book.AddPage(self.pnl_language, _("Language")) 44 self.book.AddPage(self.pnl_language, _("Language"))
43 45
44 line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL) 46 line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL)
@@ -69,17 +71,23 @@ class Preferences(wx.Dialog): @@ -69,17 +71,23 @@ class Preferences(wx.Dialog):
69 values = {} 71 values = {}
70 lang = self.pnl_language.GetSelection() 72 lang = self.pnl_language.GetSelection()
71 viewer = self.pnl_viewer3d.GetSelection() 73 viewer = self.pnl_viewer3d.GetSelection()
  74 + viewer2d = self.pnl_viewer2d.GetSelection()
72 values.update(lang) 75 values.update(lang)
73 values.update(viewer) 76 values.update(viewer)
  77 + values.update(viewer2d)
  78 +
74 return values 79 return values
75 80
76 def LoadPreferences(self, pub_evt): 81 def LoadPreferences(self, pub_evt):
77 se = ses.Session() 82 se = ses.Session()
  83 +
78 values = {const.RENDERING:se.rendering, 84 values = {const.RENDERING:se.rendering,
79 const.SURFACE_INTERPOLATION:se.surface_interpolation, 85 const.SURFACE_INTERPOLATION:se.surface_interpolation,
80 - const.LANGUAGE:se.language 86 + const.LANGUAGE:se.language,
  87 + const.SLICE_INTERPOLATION: se.slice_interpolation,
81 } 88 }
82 89
  90 + self.pnl_viewer2d.LoadSelection(values)
83 self.pnl_viewer3d.LoadSelection(values) 91 self.pnl_viewer3d.LoadSelection(values)
84 self.pnl_language.LoadSelection(values) 92 self.pnl_language.LoadSelection(values)
85 93
@@ -135,6 +143,42 @@ class Viewer3D(wx.Panel): @@ -135,6 +143,42 @@ class Viewer3D(wx.Panel):
135 self.rb_rendering.SetSelection(int(rendering)) 143 self.rb_rendering.SetSelection(int(rendering))
136 self.rb_inter.SetSelection(int(surface_interpolation)) 144 self.rb_inter.SetSelection(int(surface_interpolation))
137 145
  146 +
  147 +class Viewer2D(wx.Panel):
  148 +
  149 + def __init__(self, parent):
  150 +
  151 + wx.Panel.__init__(self, parent)
  152 +
  153 + box_visualization = wx.StaticBox(self, -1, _("Slices"))
  154 + bsizer = wx.StaticBoxSizer(box_visualization, wx.VERTICAL)
  155 +
  156 + lbl_inter = wx.StaticText(self, -1, _("Interpolated "))
  157 + bsizer.Add(lbl_inter, 0, wx.TOP|wx.LEFT, 10)
  158 +
  159 + rb_inter = self.rb_inter = wx.RadioBox(self, -1, "", wx.DefaultPosition, wx.DefaultSize,
  160 + [_('Yes'), _('No')], 3, wx.RA_SPECIFY_COLS | wx.NO_BORDER)
  161 +
  162 + bsizer.Add(rb_inter, 0, wx.TOP|wx.LEFT, 0)
  163 +
  164 + border = wx.BoxSizer(wx.VERTICAL)
  165 + border.Add(bsizer, 50, wx.EXPAND|wx.ALL, 10)
  166 + self.SetSizer(border)
  167 +
  168 + border.Fit(self)
  169 +
  170 +
  171 + def GetSelection(self):
  172 +
  173 + options = {const.SLICE_INTERPOLATION:self.rb_inter.GetSelection()}
  174 +
  175 + return options
  176 +
  177 + def LoadSelection(self, values):
  178 + value = values[const.SLICE_INTERPOLATION]
  179 + self.rb_inter.SetSelection(int(value))
  180 +
  181 +
138 class Language(wx.Panel): 182 class Language(wx.Panel):
139 183
140 def __init__(self, parent): 184 def __init__(self, parent):
invesalius/session.py
@@ -70,6 +70,7 @@ class Session(object): @@ -70,6 +70,7 @@ class Session(object):
70 self.recent_projects = [(const.SAMPLE_DIR, "Cranium.inv3")] 70 self.recent_projects = [(const.SAMPLE_DIR, "Cranium.inv3")]
71 self.last_dicom_folder = '' 71 self.last_dicom_folder = ''
72 self.surface_interpolation = 1 72 self.surface_interpolation = 1
  73 + self.slice_interpolation = 0
73 self.rendering = 0 74 self.rendering = 0
74 self.WriteSessionFile() 75 self.WriteSessionFile()
75 76
@@ -162,6 +163,7 @@ class Session(object): @@ -162,6 +163,7 @@ class Session(object):
162 config.set('session', 'random_id', self.random_id) 163 config.set('session', 'random_id', self.random_id)
163 config.set('session', 'surface_interpolation', self.surface_interpolation) 164 config.set('session', 'surface_interpolation', self.surface_interpolation)
164 config.set('session', 'rendering', self.rendering) 165 config.set('session', 'rendering', self.rendering)
  166 + config.set('session', 'slice_interpolation', self.slice_interpolation)
165 167
166 config.add_section('project') 168 config.add_section('project')
167 config.set('project', 'recent_projects', self.recent_projects) 169 config.set('project', 'recent_projects', self.recent_projects)
@@ -261,6 +263,8 @@ class Session(object): @@ -261,6 +263,8 @@ class Session(object):
261 self.last_dicom_folder = self.last_dicom_folder.decode('utf-8') 263 self.last_dicom_folder = self.last_dicom_folder.decode('utf-8')
262 264
263 self.surface_interpolation = config.get('session', 'surface_interpolation') 265 self.surface_interpolation = config.get('session', 'surface_interpolation')
  266 + self.slice_interpolation = config.get('session', 'slice_interpolation')
  267 +
264 self.rendering = config.get('session', 'rendering') 268 self.rendering = config.get('session', 'rendering')
265 self.random_id = config.get('session','random_id') 269 self.random_id = config.get('session','random_id')
266 return True 270 return True
@@ -277,6 +281,7 @@ class Session(object): @@ -277,6 +281,7 @@ class Session(object):
277 except(ConfigParser.NoOptionError): 281 except(ConfigParser.NoOptionError):
278 #Added to fix new version compatibility 282 #Added to fix new version compatibility
279 self.surface_interpolation = 0 283 self.surface_interpolation = 0
  284 + self.slice_interpolation = 0
280 self.rendering = 0 285 self.rendering = 0
281 self.random_id = randint(0,pow(10,16)) 286 self.random_id = randint(0,pow(10,16))
282 self.WriteSessionFile() 287 self.WriteSessionFile()