From ad7294a7bb361541c7b081ad3a121a56eff25e79 Mon Sep 17 00:00:00 2001 From: Paulo Henrique Junqueira Amorim Date: Wed, 24 Aug 2016 09:32:43 -0300 Subject: [PATCH] Added interpolated slice option --- invesalius/constants.py | 4 ++-- invesalius/data/viewer_slice.py | 36 ++++++++++++++++++++++++++++++++++-- invesalius/gui/frame.py | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- invesalius/gui/preferences.py | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- invesalius/session.py | 5 +++++ 5 files changed, 144 insertions(+), 10 deletions(-) diff --git a/invesalius/constants.py b/invesalius/constants.py index d9a1717..c9fe27e 100644 --- a/invesalius/constants.py +++ b/invesalius/constants.py @@ -453,7 +453,7 @@ VTK_WARNING = 0 [ID_DICOM_IMPORT, ID_PROJECT_OPEN, ID_PROJECT_SAVE_AS, ID_PROJECT_SAVE, ID_PROJECT_CLOSE, ID_PROJECT_INFO, ID_SAVE_SCREENSHOT, ID_DICOM_LOAD_NET, ID_PRINT_SCREENSHOT, ID_IMPORT_OTHERS_FILES, ID_ANALYZE_IMPORT, ID_PREFERENCES, -ID_DICOM_NETWORK, ID_TIFF_JPG_PNG] = [wx.NewId() for number in range(14)] +ID_DICOM_NETWORK, ID_TIFF_JPG_PNG, ID_VIEW_INTERPOLATED] = [wx.NewId() for number in range(15)] ID_EXIT = wx.ID_EXIT ID_ABOUT = wx.ID_ABOUT @@ -549,7 +549,7 @@ STYLE_LEVEL = {SLICE_STATE_EDITOR: 1, RENDERING = 0 SURFACE_INTERPOLATION = 1 LANGUAGE = 2 - +SLICE_INTERPOLATION = 3 #Correlaction extracted from pyDicom DICOM_ENCODING_TO_PYTHON = { diff --git a/invesalius/data/viewer_slice.py b/invesalius/data/viewer_slice.py index c9cbead..5299af2 100755 --- a/invesalius/data/viewer_slice.py +++ b/invesalius/data/viewer_slice.py @@ -45,7 +45,7 @@ import data.vtk_utils as vtku import project import slice_data as sd import utils - +import session as ses from data import converters from data import measures @@ -525,6 +525,10 @@ class Viewer(wx.Panel): # All renderers and image actors in this viewer self.slice_data_list = [] self.slice_data = None + + self.slice_actor = None + self.interpolation_slice_status = True + # The layout from slice_data, the first is number of cols, the second # is the number of rows self.layout = (1, 1) @@ -1085,6 +1089,8 @@ class Viewer(wx.Panel): Publisher.subscribe(self.OnSetOverwriteMask, "Set overwrite mask") Publisher.subscribe(self.RefreshViewer, "Refresh viewer") + Publisher.subscribe(self.SetInterpolatedSlices, "Set interpolated slices") + Publisher.subscribe(self.UpdateInterpolatedSlice, "Update Slice Interpolation") def RefreshViewer(self, pubsub_evt): @@ -1342,9 +1348,15 @@ class Viewer(wx.Panel): self.interactor.GetRenderWindow().AddRenderer(renderer) actor = vtk.vtkImageActor() + self.slice_actor = actor # TODO: Create a option to let the user set if he wants to interpolate # the slice images. - actor.InterpolateOff() + + if int(ses.Session().slice_interpolation) == 1: + actor.InterpolateOff() + else: + actor.InterpolateOn() + slice_data = sd.SliceData() slice_data.SetOrientation(self.orientation) slice_data.renderer = renderer @@ -1358,6 +1370,26 @@ class Viewer(wx.Panel): return slice_data + def UpdateInterpolatedSlice(self, pub_sub): + if self.slice_actor != None: + if ses.Session().slice_interpolation: + self.slice_actor.InterpolateOff() + else: + self.slice_actor.InterpolateOn() + self.interactor.Render() + + + def SetInterpolatedSlices(self, pub_sub): + self.interpolation_slice_status = status = pub_sub.data + + if self.slice_actor != None: + if status == True: + self.slice_actor.InterpolateOn() + else: + self.slice_actor.InterpolateOff() + + self.interactor.Render() + def __update_camera(self): orientation = self.orientation proj = project.Project() diff --git a/invesalius/gui/frame.py b/invesalius/gui/frame.py index 90e10f3..4d54aed 100644 --- a/invesalius/gui/frame.py +++ b/invesalius/gui/frame.py @@ -85,6 +85,7 @@ class Frame(wx.Frame): self.mw = None + if sys.platform != 'darwin': self.Maximize() @@ -95,8 +96,13 @@ class Frame(wx.Frame): #self.SetSize(wx.Size(1024, 748)) + #to control check and unckeck of menu view -> interpolated_slices + main_menu = MenuBar(self) + + self.actived_interpolated_slices = main_menu.view_menu + # Set menus, status and task bar - self.SetMenuBar(MenuBar(self)) + self.SetMenuBar(main_menu) self.SetStatusBar(StatusBar(self)) # Set TaskBarIcon @@ -445,6 +451,20 @@ class Frame(wx.Frame): elif id == const.ID_REMOVE_MASK_PART: self.OnRemoveMaskParts() + elif id == const.ID_VIEW_INTERPOLATED: + + st = self.actived_interpolated_slices.IsChecked(const.ID_VIEW_INTERPOLATED) + + if st: + self.OnInterpolatedSlices(True) + else: + self.OnInterpolatedSlices(False) + + def OnInterpolatedSlices(self, status): + + Publisher.sendMessage('Set interpolated slices', status) + + def OnSize(self, evt): """ Refresh GUI when frame is resized. @@ -478,9 +498,12 @@ class Frame(wx.Frame): ses.Session().rendering = values[const.RENDERING] ses.Session().surface_interpolation = values[const.SURFACE_INTERPOLATION] ses.Session().language = values[const.LANGUAGE] + ses.Session().slice_interpolation = values[const.SLICE_INTERPOLATION] Publisher.sendMessage('Remove Volume') Publisher.sendMessage('Reset Reaycasting') + Publisher.sendMessage('Update Slice Interpolation') + Publisher.sendMessage('Update Slice Interpolation MenuBar') Publisher.sendMessage('Update Surface Interpolation') def ShowAbout(self): @@ -614,6 +637,7 @@ class MenuBar(wx.MenuBar): sub(self.OnAddMask, "Add mask") sub(self.OnRemoveMasks, "Remove masks") sub(self.OnShowMask, "Show mask") + sub(self.OnUpdateSliceInterpolation, "Update Slice Interpolation MenuBar") self.num_masks = 0 @@ -718,7 +742,19 @@ class MenuBar(wx.MenuBar): tools_menu.AppendMenu(-1, _(u'Image'), image_menu) - # VIEW + #View + + self.view_menu = view_menu = wx.Menu() + view_menu.Append(const.ID_VIEW_INTERPOLATED, _(u'Interpolated slices'), "", wx.ITEM_CHECK) + + + v = self.SliceInterpolationStatus() + self.view_menu.Check(const.ID_VIEW_INTERPOLATED, v) + + self.actived_interpolated_slices = self.view_menu + + + #view_tool_menu = wx.Menu() #app = view_tool_menu.Append #app(const.ID_TOOL_PROJECT, "Project Toolbar") @@ -765,12 +801,29 @@ class MenuBar(wx.MenuBar): # Add all menus to menubar self.Append(file_menu, _("File")) self.Append(file_edit, _("Edit")) + self.Append(view_menu, _(u"View")) self.Append(tools_menu, _(u"Tools")) - #self.Append(view_menu, "View") #self.Append(tools_menu, "Tools") self.Append(options_menu, _("Options")) self.Append(help_menu, _("Help")) + + def SliceInterpolationStatus(self): + + status = int(ses.Session().slice_interpolation) + + if status == 0: + v = True + else: + v = False + + return v + + def OnUpdateSliceInterpolation(self, pubsub_evt): + v = self.SliceInterpolationStatus() + self.view_menu.Check(const.ID_VIEW_INTERPOLATED, v) + + def OnEnableState(self, pubsub_evt): """ Based on given state, enables or disables menu items which diff --git a/invesalius/gui/preferences.py b/invesalius/gui/preferences.py index 75dc0da..2ad6a80 100644 --- a/invesalius/gui/preferences.py +++ b/invesalius/gui/preferences.py @@ -26,7 +26,7 @@ class Preferences(wx.Dialog): sizer = wx.BoxSizer(wx.VERTICAL) - bookStyle = fnb.FNB_NODRAG | fnb.FNB_NO_NAV_BUTTONS | fnb.FNB_NO_X_BUTTON + bookStyle = fnb.FNB_NODRAG | fnb.FNB_NO_X_BUTTON if AGW: self.book = fnb.FlatNotebook(self, wx.ID_ANY, agwStyle=bookStyle) @@ -35,10 +35,12 @@ class Preferences(wx.Dialog): sizer.Add(self.book, 80, wx.EXPAND|wx.ALL) + self.pnl_viewer2d = Viewer2D(self) self.pnl_viewer3d = Viewer3D(self) self.pnl_language = Language(self) - self.book.AddPage(self.pnl_viewer3d, _("Visualization")) + self.book.AddPage(self.pnl_viewer2d, _("2D Visualization")) + self.book.AddPage(self.pnl_viewer3d, _("3D Visualization")) self.book.AddPage(self.pnl_language, _("Language")) line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL) @@ -69,17 +71,23 @@ class Preferences(wx.Dialog): values = {} lang = self.pnl_language.GetSelection() viewer = self.pnl_viewer3d.GetSelection() + viewer2d = self.pnl_viewer2d.GetSelection() values.update(lang) values.update(viewer) + values.update(viewer2d) + return values def LoadPreferences(self, pub_evt): se = ses.Session() + values = {const.RENDERING:se.rendering, const.SURFACE_INTERPOLATION:se.surface_interpolation, - const.LANGUAGE:se.language + const.LANGUAGE:se.language, + const.SLICE_INTERPOLATION: se.slice_interpolation, } + self.pnl_viewer2d.LoadSelection(values) self.pnl_viewer3d.LoadSelection(values) self.pnl_language.LoadSelection(values) @@ -135,6 +143,42 @@ class Viewer3D(wx.Panel): self.rb_rendering.SetSelection(int(rendering)) self.rb_inter.SetSelection(int(surface_interpolation)) + +class Viewer2D(wx.Panel): + + def __init__(self, parent): + + wx.Panel.__init__(self, parent) + + box_visualization = wx.StaticBox(self, -1, _("Slices")) + bsizer = wx.StaticBoxSizer(box_visualization, wx.VERTICAL) + + lbl_inter = wx.StaticText(self, -1, _("Interpolated ")) + bsizer.Add(lbl_inter, 0, wx.TOP|wx.LEFT, 10) + + rb_inter = self.rb_inter = wx.RadioBox(self, -1, "", wx.DefaultPosition, wx.DefaultSize, + [_('Yes'), _('No')], 3, wx.RA_SPECIFY_COLS | wx.NO_BORDER) + + bsizer.Add(rb_inter, 0, wx.TOP|wx.LEFT, 0) + + border = wx.BoxSizer(wx.VERTICAL) + border.Add(bsizer, 50, wx.EXPAND|wx.ALL, 10) + self.SetSizer(border) + + border.Fit(self) + + + def GetSelection(self): + + options = {const.SLICE_INTERPOLATION:self.rb_inter.GetSelection()} + + return options + + def LoadSelection(self, values): + value = values[const.SLICE_INTERPOLATION] + self.rb_inter.SetSelection(int(value)) + + class Language(wx.Panel): def __init__(self, parent): diff --git a/invesalius/session.py b/invesalius/session.py index 344bf3e..6f540f9 100644 --- a/invesalius/session.py +++ b/invesalius/session.py @@ -70,6 +70,7 @@ class Session(object): self.recent_projects = [(const.SAMPLE_DIR, "Cranium.inv3")] self.last_dicom_folder = '' self.surface_interpolation = 1 + self.slice_interpolation = 0 self.rendering = 0 self.WriteSessionFile() @@ -162,6 +163,7 @@ class Session(object): config.set('session', 'random_id', self.random_id) config.set('session', 'surface_interpolation', self.surface_interpolation) config.set('session', 'rendering', self.rendering) + config.set('session', 'slice_interpolation', self.slice_interpolation) config.add_section('project') config.set('project', 'recent_projects', self.recent_projects) @@ -261,6 +263,8 @@ class Session(object): self.last_dicom_folder = self.last_dicom_folder.decode('utf-8') self.surface_interpolation = config.get('session', 'surface_interpolation') + self.slice_interpolation = config.get('session', 'slice_interpolation') + self.rendering = config.get('session', 'rendering') self.random_id = config.get('session','random_id') return True @@ -277,6 +281,7 @@ class Session(object): except(ConfigParser.NoOptionError): #Added to fix new version compatibility self.surface_interpolation = 0 + self.slice_interpolation = 0 self.rendering = 0 self.random_id = randint(0,pow(10,16)) self.WriteSessionFile() -- libgit2 0.21.2