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 453 [ID_DICOM_IMPORT, ID_PROJECT_OPEN, ID_PROJECT_SAVE_AS, ID_PROJECT_SAVE,
454 454 ID_PROJECT_CLOSE, ID_PROJECT_INFO, ID_SAVE_SCREENSHOT, ID_DICOM_LOAD_NET,
455 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 457 ID_EXIT = wx.ID_EXIT
458 458 ID_ABOUT = wx.ID_ABOUT
459 459  
... ... @@ -549,7 +549,7 @@ STYLE_LEVEL = {SLICE_STATE_EDITOR: 1,
549 549 RENDERING = 0
550 550 SURFACE_INTERPOLATION = 1
551 551 LANGUAGE = 2
552   -
  552 +SLICE_INTERPOLATION = 3
553 553  
554 554 #Correlaction extracted from pyDicom
555 555 DICOM_ENCODING_TO_PYTHON = {
... ...
invesalius/data/viewer_slice.py
... ... @@ -45,7 +45,7 @@ import data.vtk_utils as vtku
45 45 import project
46 46 import slice_data as sd
47 47 import utils
48   -
  48 +import session as ses
49 49 from data import converters
50 50  
51 51 from data import measures
... ... @@ -525,6 +525,10 @@ class Viewer(wx.Panel):
525 525 # All renderers and image actors in this viewer
526 526 self.slice_data_list = []
527 527 self.slice_data = None
  528 +
  529 + self.slice_actor = None
  530 + self.interpolation_slice_status = True
  531 +
528 532 # The layout from slice_data, the first is number of cols, the second
529 533 # is the number of rows
530 534 self.layout = (1, 1)
... ... @@ -1085,6 +1089,8 @@ class Viewer(wx.Panel):
1085 1089 Publisher.subscribe(self.OnSetOverwriteMask, "Set overwrite mask")
1086 1090  
1087 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 1096 def RefreshViewer(self, pubsub_evt):
... ... @@ -1342,9 +1348,15 @@ class Viewer(wx.Panel):
1342 1348 self.interactor.GetRenderWindow().AddRenderer(renderer)
1343 1349  
1344 1350 actor = vtk.vtkImageActor()
  1351 + self.slice_actor = actor
1345 1352 # TODO: Create a option to let the user set if he wants to interpolate
1346 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 1360 slice_data = sd.SliceData()
1349 1361 slice_data.SetOrientation(self.orientation)
1350 1362 slice_data.renderer = renderer
... ... @@ -1358,6 +1370,26 @@ class Viewer(wx.Panel):
1358 1370  
1359 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 1393 def __update_camera(self):
1362 1394 orientation = self.orientation
1363 1395 proj = project.Project()
... ...
invesalius/gui/frame.py
... ... @@ -85,6 +85,7 @@ class Frame(wx.Frame):
85 85  
86 86 self.mw = None
87 87  
  88 +
88 89 if sys.platform != 'darwin':
89 90 self.Maximize()
90 91  
... ... @@ -95,8 +96,13 @@ class Frame(wx.Frame):
95 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 104 # Set menus, status and task bar
99   - self.SetMenuBar(MenuBar(self))
  105 + self.SetMenuBar(main_menu)
100 106 self.SetStatusBar(StatusBar(self))
101 107  
102 108 # Set TaskBarIcon
... ... @@ -445,6 +451,20 @@ class Frame(wx.Frame):
445 451 elif id == const.ID_REMOVE_MASK_PART:
446 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 468 def OnSize(self, evt):
449 469 """
450 470 Refresh GUI when frame is resized.
... ... @@ -478,9 +498,12 @@ class Frame(wx.Frame):
478 498 ses.Session().rendering = values[const.RENDERING]
479 499 ses.Session().surface_interpolation = values[const.SURFACE_INTERPOLATION]
480 500 ses.Session().language = values[const.LANGUAGE]
  501 + ses.Session().slice_interpolation = values[const.SLICE_INTERPOLATION]
481 502  
482 503 Publisher.sendMessage('Remove Volume')
483 504 Publisher.sendMessage('Reset Reaycasting')
  505 + Publisher.sendMessage('Update Slice Interpolation')
  506 + Publisher.sendMessage('Update Slice Interpolation MenuBar')
484 507 Publisher.sendMessage('Update Surface Interpolation')
485 508  
486 509 def ShowAbout(self):
... ... @@ -614,6 +637,7 @@ class MenuBar(wx.MenuBar):
614 637 sub(self.OnAddMask, "Add mask")
615 638 sub(self.OnRemoveMasks, "Remove masks")
616 639 sub(self.OnShowMask, "Show mask")
  640 + sub(self.OnUpdateSliceInterpolation, "Update Slice Interpolation MenuBar")
617 641  
618 642 self.num_masks = 0
619 643  
... ... @@ -718,7 +742,19 @@ class MenuBar(wx.MenuBar):
718 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 758 #view_tool_menu = wx.Menu()
723 759 #app = view_tool_menu.Append
724 760 #app(const.ID_TOOL_PROJECT, "Project Toolbar")
... ... @@ -765,12 +801,29 @@ class MenuBar(wx.MenuBar):
765 801 # Add all menus to menubar
766 802 self.Append(file_menu, _("File"))
767 803 self.Append(file_edit, _("Edit"))
  804 + self.Append(view_menu, _(u"View"))
768 805 self.Append(tools_menu, _(u"Tools"))
769   - #self.Append(view_menu, "View")
770 806 #self.Append(tools_menu, "Tools")
771 807 self.Append(options_menu, _("Options"))
772 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 827 def OnEnableState(self, pubsub_evt):
775 828 """
776 829 Based on given state, enables or disables menu items which
... ...
invesalius/gui/preferences.py
... ... @@ -26,7 +26,7 @@ class Preferences(wx.Dialog):
26 26  
27 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 31 if AGW:
32 32 self.book = fnb.FlatNotebook(self, wx.ID_ANY, agwStyle=bookStyle)
... ... @@ -35,10 +35,12 @@ class Preferences(wx.Dialog):
35 35  
36 36 sizer.Add(self.book, 80, wx.EXPAND|wx.ALL)
37 37  
  38 + self.pnl_viewer2d = Viewer2D(self)
38 39 self.pnl_viewer3d = Viewer3D(self)
39 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 44 self.book.AddPage(self.pnl_language, _("Language"))
43 45  
44 46 line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL)
... ... @@ -69,17 +71,23 @@ class Preferences(wx.Dialog):
69 71 values = {}
70 72 lang = self.pnl_language.GetSelection()
71 73 viewer = self.pnl_viewer3d.GetSelection()
  74 + viewer2d = self.pnl_viewer2d.GetSelection()
72 75 values.update(lang)
73 76 values.update(viewer)
  77 + values.update(viewer2d)
  78 +
74 79 return values
75 80  
76 81 def LoadPreferences(self, pub_evt):
77 82 se = ses.Session()
  83 +
78 84 values = {const.RENDERING:se.rendering,
79 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 91 self.pnl_viewer3d.LoadSelection(values)
84 92 self.pnl_language.LoadSelection(values)
85 93  
... ... @@ -135,6 +143,42 @@ class Viewer3D(wx.Panel):
135 143 self.rb_rendering.SetSelection(int(rendering))
136 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 182 class Language(wx.Panel):
139 183  
140 184 def __init__(self, parent):
... ...
invesalius/session.py
... ... @@ -70,6 +70,7 @@ class Session(object):
70 70 self.recent_projects = [(const.SAMPLE_DIR, "Cranium.inv3")]
71 71 self.last_dicom_folder = ''
72 72 self.surface_interpolation = 1
  73 + self.slice_interpolation = 0
73 74 self.rendering = 0
74 75 self.WriteSessionFile()
75 76  
... ... @@ -162,6 +163,7 @@ class Session(object):
162 163 config.set('session', 'random_id', self.random_id)
163 164 config.set('session', 'surface_interpolation', self.surface_interpolation)
164 165 config.set('session', 'rendering', self.rendering)
  166 + config.set('session', 'slice_interpolation', self.slice_interpolation)
165 167  
166 168 config.add_section('project')
167 169 config.set('project', 'recent_projects', self.recent_projects)
... ... @@ -261,6 +263,8 @@ class Session(object):
261 263 self.last_dicom_folder = self.last_dicom_folder.decode('utf-8')
262 264  
263 265 self.surface_interpolation = config.get('session', 'surface_interpolation')
  266 + self.slice_interpolation = config.get('session', 'slice_interpolation')
  267 +
264 268 self.rendering = config.get('session', 'rendering')
265 269 self.random_id = config.get('session','random_id')
266 270 return True
... ... @@ -277,6 +281,7 @@ class Session(object):
277 281 except(ConfigParser.NoOptionError):
278 282 #Added to fix new version compatibility
279 283 self.surface_interpolation = 0
  284 + self.slice_interpolation = 0
280 285 self.rendering = 0
281 286 self.random_id = randint(0,pow(10,16))
282 287 self.WriteSessionFile()
... ...