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() | ... | ... |