Commit ad7294a7bb361541c7b081ad3a121a56eff25e79
Committed by
GitHub
1 parent
2c9f1dc3
Exists in
master
and in
21 other branches
Added interpolated slice option
* ADD: Added slice interpolation optioni into menubar * ADD: Added slice interpolation optioni into menubar * ADD: Added interpolation into preferences
Showing
5 changed files
with
144 additions
and
10 deletions
Show diff stats
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() | ... | ... |