Commit eb6cd6beada052bc779de1b8132d68e73fe6fb51
1 parent
8e4857dd
Exists in
master
and in
68 other branches
ENH: (underdevel) Open inv3 project in GUI - currently there is a problem on loa…
…ding masks' imagedatas
Showing
8 changed files
with
152 additions
and
34 deletions
Show diff stats
invesalius/control.py
@@ -138,7 +138,11 @@ class Controller(): | @@ -138,7 +138,11 @@ class Controller(): | ||
138 | def LoadProject(self): | 138 | def LoadProject(self): |
139 | proj = prj.Project() | 139 | proj = prj.Project() |
140 | ps.Publisher().sendMessage('Set project name', proj.name) | 140 | ps.Publisher().sendMessage('Set project name', proj.name) |
141 | - ps.Publisher().sendMessage('Load slice to viewer', (proj.imagedata)) | 141 | + ps.Publisher().sendMessage('Load slice to viewer', |
142 | + (proj.imagedata, | ||
143 | + proj.mask_dict)) | ||
144 | + ps.Publisher().sendMessage('Load surface dict', | ||
145 | + proj.surface_dict) | ||
142 | self.LoadImagedataInfo() # TODO: where do we insert this <<<? | 146 | self.LoadImagedataInfo() # TODO: where do we insert this <<<? |
143 | ps.Publisher().sendMessage('Bright and contrast adjustment image',\ | 147 | ps.Publisher().sendMessage('Bright and contrast adjustment image',\ |
144 | (proj.window, proj.level)) | 148 | (proj.window, proj.level)) |
@@ -172,8 +176,10 @@ class Controller(): | @@ -172,8 +176,10 @@ class Controller(): | ||
172 | 176 | ||
173 | proj = prj.Project() | 177 | proj = prj.Project() |
174 | proj.name = dicom.patient.name | 178 | proj.name = dicom.patient.name |
179 | + proj.modality = dicom.acquisition.modality | ||
175 | proj.SetAcquisitionModality(dicom.acquisition.modality) | 180 | proj.SetAcquisitionModality(dicom.acquisition.modality) |
176 | proj.imagedata = imagedata | 181 | proj.imagedata = imagedata |
182 | + #proj.dicom = dicom | ||
177 | proj.original_orientation =\ | 183 | proj.original_orientation =\ |
178 | name_to_const[dicom.image.orientation_label] | 184 | name_to_const[dicom.image.orientation_label] |
179 | proj.window = float(dicom.image.window) | 185 | proj.window = float(dicom.image.window) |
@@ -226,7 +232,9 @@ class Controller(): | @@ -226,7 +232,9 @@ class Controller(): | ||
226 | 232 | ||
227 | # Set default value into slices' default mask | 233 | # Set default value into slices' default mask |
228 | key= thresh_modes[const.THRESHOLD_PRESETS_INDEX] | 234 | key= thresh_modes[const.THRESHOLD_PRESETS_INDEX] |
229 | - (min_thresh, max_thresh) = proj.threshold_modes.get_value(key) | 235 | + #value = proj.threshold_modes.get_value(key) |
236 | + value = proj.threshold_modes[key] | ||
237 | + (min_thresh, max_thresh) = value | ||
230 | 238 | ||
231 | def LoadRaycastingPreset(self, pubsub_evt): | 239 | def LoadRaycastingPreset(self, pubsub_evt): |
232 | label = pubsub_evt.data | 240 | label = pubsub_evt.data |
@@ -260,4 +268,14 @@ class Controller(): | @@ -260,4 +268,14 @@ class Controller(): | ||
260 | 268 | ||
261 | def OnOpenProject(self, pubsub_evt): | 269 | def OnOpenProject(self, pubsub_evt): |
262 | filename = pubsub_evt.data | 270 | filename = pubsub_evt.data |
263 | - prj.Project().OpenPlistProject(filename) | 271 | + |
272 | + proj = prj.Project() | ||
273 | + proj.OpenPlistProject(filename) | ||
274 | + proj.SetAcquisitionModality(proj.modality) | ||
275 | + | ||
276 | + const.THRESHOLD_OUTVALUE = proj.threshold_range[0] | ||
277 | + const.THRESHOLD_INVALUE = proj.threshold_range[1] | ||
278 | + const.WINDOW_LEVEL['Default'] = (proj.window, proj.level) | ||
279 | + const.WINDOW_LEVEL['Manual'] = (proj.window, proj.level) | ||
280 | + | ||
281 | + self.LoadProject() |
invesalius/data/imagedata_utils.py
@@ -169,9 +169,15 @@ def Import(filename): | @@ -169,9 +169,15 @@ def Import(filename): | ||
169 | reader = vtk.vtkXMLImageDataReader() | 169 | reader = vtk.vtkXMLImageDataReader() |
170 | reader.SetFileName(filename) | 170 | reader.SetFileName(filename) |
171 | # TODO: Check if the code bellow is necessary | 171 | # TODO: Check if the code bellow is necessary |
172 | - #reader.WholeSlicesOn() | 172 | + reader.WholeSlicesOn() |
173 | reader.Update() | 173 | reader.Update() |
174 | - return reader.GetOutput() | 174 | + |
175 | + cast = vtk.vtkImageCast() | ||
176 | + cast.SetInput(reader.GetOutput()) | ||
177 | + cast.SetOutputScalarType(11) | ||
178 | + cast.Update() | ||
179 | + | ||
180 | + return cast.GetOutput() | ||
175 | 181 | ||
176 | def View(imagedata): | 182 | def View(imagedata): |
177 | viewer = vtk.vtkImageViewer() | 183 | viewer = vtk.vtkImageViewer() |
invesalius/data/slice_.py
@@ -325,12 +325,19 @@ class Slice(object): | @@ -325,12 +325,19 @@ class Slice(object): | ||
325 | 325 | ||
326 | 326 | ||
327 | 327 | ||
328 | - def SetInput(self, imagedata): | 328 | + def SetInput(self, imagedata, mask_dict): |
329 | self.imagedata = imagedata | 329 | self.imagedata = imagedata |
330 | self.extent = imagedata.GetExtent() | 330 | self.extent = imagedata.GetExtent() |
331 | 331 | ||
332 | imagedata_bg = self.__create_background(imagedata) | 332 | imagedata_bg = self.__create_background(imagedata) |
333 | - imagedata_mask = self.__create_mask(imagedata) | 333 | + |
334 | + if not mask_dict: | ||
335 | + imagedata_mask = self.__build_mask(imagedata, create=True) | ||
336 | + else: | ||
337 | + self.__load_masks(mask_dict) | ||
338 | + imagedata_mask = self.current_mask.imagedata | ||
339 | + | ||
340 | + | ||
334 | 341 | ||
335 | mask_opacity = self.current_mask.opacity | 342 | mask_opacity = self.current_mask.opacity |
336 | 343 | ||
@@ -343,7 +350,17 @@ class Slice(object): | @@ -343,7 +350,17 @@ class Slice(object): | ||
343 | else: | 350 | else: |
344 | blend_filter.SetOpacity(1, 0) | 351 | blend_filter.SetOpacity(1, 0) |
345 | blend_filter.SetInput(0, imagedata_bg) | 352 | blend_filter.SetInput(0, imagedata_bg) |
353 | + | ||
354 | + #cast = vtk.vtkImageCast() | ||
355 | + ##cast.SetInput(imagedata_mask) | ||
356 | + #cast.SetOutputScalarType(3) | ||
357 | + #cast.Update() | ||
358 | + print 1 | ||
359 | + #blend_filter.SetInput(1, cast.GetOutput()) | ||
346 | blend_filter.SetInput(1, imagedata_mask) | 360 | blend_filter.SetInput(1, imagedata_mask) |
361 | + print "******", imagedata_mask.GetScalarType() #11 | ||
362 | + print "******", imagedata_bg.GetScalarType() #11 | ||
363 | + print 2 | ||
347 | blend_filter.SetBlendModeToNormal() | 364 | blend_filter.SetBlendModeToNormal() |
348 | blend_filter.GetOutput().ReleaseDataFlagOn() | 365 | blend_filter.GetOutput().ReleaseDataFlagOn() |
349 | self.blend_filter = blend_filter | 366 | self.blend_filter = blend_filter |
@@ -508,10 +525,31 @@ class Slice(object): | @@ -508,10 +525,31 @@ class Slice(object): | ||
508 | ps.Publisher().sendMessage('Update slice viewer') | 525 | ps.Publisher().sendMessage('Update slice viewer') |
509 | 526 | ||
510 | 527 | ||
528 | + def __load_masks(self, mask_dict): | ||
529 | + keys = mask_dict.keys() | ||
530 | + keys.sort() | ||
531 | + for key in keys: | ||
532 | + mask = mask_dict[key] | ||
533 | + | ||
534 | + # update gui related to mask | ||
535 | + ps.Publisher().sendMessage('Add mask', | ||
536 | + (mask.index, | ||
537 | + mask.name, | ||
538 | + mask.threshold_range, | ||
539 | + mask.colour)) | ||
540 | + | ||
541 | + self.current_mask = mask | ||
542 | + self.__build_mask(mask.imagedata, False) | ||
543 | + | ||
544 | + ps.Publisher().sendMessage('Change mask selected', mask.index) | ||
545 | + ps.Publisher().sendMessage('Update slice viewer') | ||
546 | + | ||
547 | + | ||
511 | 548 | ||
512 | - def __create_mask(self, imagedata): | 549 | + def __build_mask(self, imagedata, create=True): |
513 | # create new mask instance and insert it into project | 550 | # create new mask instance and insert it into project |
514 | - self.CreateMask(imagedata=imagedata) | 551 | + if create: |
552 | + self.CreateMask(imagedata=imagedata) | ||
515 | current_mask = self.current_mask | 553 | current_mask = self.current_mask |
516 | 554 | ||
517 | # properties to be inserted into pipeline | 555 | # properties to be inserted into pipeline |
invesalius/data/surface.py
@@ -100,6 +100,44 @@ class SurfaceManager(): | @@ -100,6 +100,44 @@ class SurfaceManager(): | ||
100 | ps.Publisher().subscribe(self.OnChangeSurfaceName, 'Change surface name') | 100 | ps.Publisher().subscribe(self.OnChangeSurfaceName, 'Change surface name') |
101 | ps.Publisher().subscribe(self.OnShowSurface, 'Show surface') | 101 | ps.Publisher().subscribe(self.OnShowSurface, 'Show surface') |
102 | ps.Publisher().subscribe(self.OnExportSurface,'Export surface to file') | 102 | ps.Publisher().subscribe(self.OnExportSurface,'Export surface to file') |
103 | + ps.Publisher().subscribe(self.OnLoadSurfaceDict, 'Load surface dict') | ||
104 | + | ||
105 | + def OnLoadSurfaceDict(self, pubsub_evt): | ||
106 | + surface_dict = pubsub_evt.data | ||
107 | + | ||
108 | + for key in surface_dict: | ||
109 | + surface = surface_dict[key] | ||
110 | + # Map polygonal data (vtkPolyData) to graphics primitives. | ||
111 | + mapper = vtk.vtkPolyDataMapper() | ||
112 | + mapper.SetInput(surface.polydata) | ||
113 | + mapper.ScalarVisibilityOff() | ||
114 | + | ||
115 | + # Represent an object (geometry & properties) in the rendered scene | ||
116 | + actor = vtk.vtkActor() | ||
117 | + actor.SetMapper(mapper) | ||
118 | + | ||
119 | + # Set actor colour and transparency | ||
120 | + actor.GetProperty().SetColor(surface.colour) | ||
121 | + actor.GetProperty().SetOpacity(1-surface.transparency) | ||
122 | + | ||
123 | + self.actors_dict[surface.index] = actor | ||
124 | + | ||
125 | + | ||
126 | + # Send actor by pubsub to viewer's render | ||
127 | + ps.Publisher().sendMessage('Load surface actor into viewer', (actor)) | ||
128 | + | ||
129 | + ps.Publisher().sendMessage('Update status text in GUI', | ||
130 | + "Surface created.") | ||
131 | + | ||
132 | + # The following lines have to be here, otherwise all volumes disappear | ||
133 | + | ||
134 | + ps.Publisher().sendMessage('Update surface info in GUI', | ||
135 | + (surface.index, surface.name, | ||
136 | + surface.colour, surface.volume, | ||
137 | + surface.transparency)) | ||
138 | + | ||
139 | + | ||
140 | + | ||
103 | 141 | ||
104 | def AddNewActor(self, pubsub_evt): | 142 | def AddNewActor(self, pubsub_evt): |
105 | """ | 143 | """ |
invesalius/data/viewer_slice.py
@@ -746,8 +746,8 @@ class Viewer(wx.Panel): | @@ -746,8 +746,8 @@ class Viewer(wx.Panel): | ||
746 | self.interactor.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu) | 746 | self.interactor.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu) |
747 | 747 | ||
748 | def LoadImagedata(self, pubsub_evt): | 748 | def LoadImagedata(self, pubsub_evt): |
749 | - imagedata = pubsub_evt.data | ||
750 | - self.SetInput(imagedata) | 749 | + imagedata, mask_dict = pubsub_evt.data |
750 | + self.SetInput(imagedata, mask_dict) | ||
751 | 751 | ||
752 | def LoadRenderers(self, image): | 752 | def LoadRenderers(self, image): |
753 | number_renderers = self.layout[0] * self.layout[1] | 753 | number_renderers = self.layout[0] * self.layout[1] |
@@ -788,7 +788,7 @@ class Viewer(wx.Panel): | @@ -788,7 +788,7 @@ class Viewer(wx.Panel): | ||
788 | self.cursor_ = cursor | 788 | self.cursor_ = cursor |
789 | return cursor | 789 | return cursor |
790 | 790 | ||
791 | - def SetInput(self, imagedata): | 791 | + def SetInput(self, imagedata, mask_dict): |
792 | self.imagedata = imagedata | 792 | self.imagedata = imagedata |
793 | 793 | ||
794 | #ren = self.ren | 794 | #ren = self.ren |
@@ -797,7 +797,7 @@ class Viewer(wx.Panel): | @@ -797,7 +797,7 @@ class Viewer(wx.Panel): | ||
797 | # Slice pipeline, to be inserted into current viewer | 797 | # Slice pipeline, to be inserted into current viewer |
798 | slice_ = sl.Slice() | 798 | slice_ = sl.Slice() |
799 | if slice_.imagedata is None: | 799 | if slice_.imagedata is None: |
800 | - slice_.SetInput(imagedata) | 800 | + slice_.SetInput(imagedata, mask_dict) |
801 | 801 | ||
802 | #actor = vtk.vtkImageActor() | 802 | #actor = vtk.vtkImageActor() |
803 | #actor.SetInput(slice_.GetOutput()) | 803 | #actor.SetInput(slice_.GetOutput()) |
invesalius/gui/task_importer.py
@@ -32,7 +32,7 @@ BTN_OPEN_PROJECT = wx.NewId() | @@ -32,7 +32,7 @@ BTN_OPEN_PROJECT = wx.NewId() | ||
32 | 32 | ||
33 | WILDCARD_OPEN = "InVesalius 1 project (*.promed)|*.promed|"\ | 33 | WILDCARD_OPEN = "InVesalius 1 project (*.promed)|*.promed|"\ |
34 | "InVesalius 2 project (*.inv)|*.inv|"\ | 34 | "InVesalius 2 project (*.inv)|*.inv|"\ |
35 | - "InVesalius 3 project (*.iv3)|*.iv3|"\ | 35 | + "InVesalius 3 project (*.inv3)|*.inv3|"\ |
36 | "All files (*.*)|*.*" | 36 | "All files (*.*)|*.*" |
37 | 37 | ||
38 | class TaskPanel(wx.Panel): | 38 | class TaskPanel(wx.Panel): |
@@ -177,7 +177,10 @@ class InnerTaskPanel(wx.Panel): | @@ -177,7 +177,10 @@ class InnerTaskPanel(wx.Panel): | ||
177 | defaultDir=path, | 177 | defaultDir=path, |
178 | defaultFile="", wildcard=WILDCARD_OPEN, | 178 | defaultFile="", wildcard=WILDCARD_OPEN, |
179 | style=wx.OPEN|wx.CHANGE_DIR) | 179 | style=wx.OPEN|wx.CHANGE_DIR) |
180 | - dlg.SetFilterIndex(3) | 180 | + if sys.platform != 'darwin': |
181 | + dlg.SetFilterIndex(2) | ||
182 | + else: | ||
183 | + dlg.SetFilterIndex(3) | ||
181 | 184 | ||
182 | # Show the dialog and retrieve the user response. If it is the OK response, | 185 | # Show the dialog and retrieve the user response. If it is the OK response, |
183 | # process the data. | 186 | # process the data. |
@@ -206,9 +209,9 @@ class InnerTaskPanel(wx.Panel): | @@ -206,9 +209,9 @@ class InnerTaskPanel(wx.Panel): | ||
206 | self.OnLinkOpenProject() | 209 | self.OnLinkOpenProject() |
207 | 210 | ||
208 | def TestLoadProjects(self): | 211 | def TestLoadProjects(self): |
209 | - self.LoadProject("test1.iv3") | ||
210 | - self.LoadProject("test2.iv3") | ||
211 | - self.LoadProject("test3.iv3") | 212 | + self.LoadProject("test1.inv3") |
213 | + self.LoadProject("test2.inv3") | ||
214 | + self.LoadProject("test3.inv3") | ||
212 | 215 | ||
213 | def LoadProject(self, proj_name="Unnamed"): | 216 | def LoadProject(self, proj_name="Unnamed"): |
214 | """ | 217 | """ |
invesalius/presets.py
@@ -105,6 +105,16 @@ class Presets(): | @@ -105,6 +105,16 @@ class Presets(): | ||
105 | return filename | 105 | return filename |
106 | 106 | ||
107 | def OpenPlist(self, filename): | 107 | def OpenPlist(self, filename): |
108 | - preset = plistlib.readPlist(filename) | ||
109 | - self.thresh_mri = TwoWaysDictionary(preset['thresh_mri']) | ||
110 | - self.thresh_ct = TwoWaysDictionary(preset['thresh_ct']) | 108 | + p = plistlib.readPlist(filename) |
109 | + d1 = p['thresh_mri'].copy() | ||
110 | + d2 = p['thresh_ct'].copy() | ||
111 | + | ||
112 | + self.thresh_mri = TwoWaysDictionary(d1) | ||
113 | + self.thresh_ct = TwoWaysDictionary(d2) | ||
114 | + | ||
115 | + | ||
116 | + | ||
117 | + def Test(self): | ||
118 | + print "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | ||
119 | + print self.thresh_ct.get_value("Bone") | ||
120 | + print "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" |
invesalius/project.py
@@ -55,6 +55,11 @@ class Project(object): | @@ -55,6 +55,11 @@ class Project(object): | ||
55 | # TODO: Discuss when this will be used. | 55 | # TODO: Discuss when this will be used. |
56 | self.imagedata = '' | 56 | self.imagedata = '' |
57 | 57 | ||
58 | + self.name = '' | ||
59 | + #self.dicom = '' | ||
60 | + self.modality = '' | ||
61 | + self.original_orientation = -1 | ||
62 | + | ||
58 | # Masks are related to vtkImageData | 63 | # Masks are related to vtkImageData |
59 | self.mask_dict = {} | 64 | self.mask_dict = {} |
60 | # Predefined threshold values | 65 | # Predefined threshold values |
@@ -65,10 +70,12 @@ class Project(object): | @@ -65,10 +70,12 @@ class Project(object): | ||
65 | self.level = '' | 70 | self.level = '' |
66 | 71 | ||
67 | self.presets = Presets() | 72 | self.presets = Presets() |
68 | - | 73 | + self.threshold_modes = self.presets.thresh_ct |
74 | + self.threshold_range = '' | ||
75 | + | ||
69 | self.original_orientation = '' | 76 | self.original_orientation = '' |
70 | # MRI ? CT? | 77 | # MRI ? CT? |
71 | - self.threshold_modes = self.presets.thresh_ct | 78 | + |
72 | 79 | ||
73 | # TODO: define how we will relate these threshold values to | 80 | # TODO: define how we will relate these threshold values to |
74 | # default threshold labels | 81 | # default threshold labels |
@@ -121,13 +128,17 @@ class Project(object): | @@ -121,13 +128,17 @@ class Project(object): | ||
121 | return self.mask_dict[index] | 128 | return self.mask_dict[index] |
122 | 129 | ||
123 | 130 | ||
124 | - def SetAcquisitionModality(self, type_): | 131 | + def SetAcquisitionModality(self, type_=None): |
132 | + if type_ is None: | ||
133 | + type_ = self.modality | ||
134 | + | ||
125 | if type_ == "MRI": | 135 | if type_ == "MRI": |
126 | self.threshold_modes = self.presets.thresh_mri | 136 | self.threshold_modes = self.presets.thresh_mri |
127 | elif type_ == "CT": | 137 | elif type_ == "CT": |
128 | self.threshold_modes = self.presets.thresh_ct | 138 | self.threshold_modes = self.presets.thresh_ct |
129 | else: | 139 | else: |
130 | print "Different Acquisition Modality!!!" | 140 | print "Different Acquisition Modality!!!" |
141 | + self.modality = type_ | ||
131 | 142 | ||
132 | def SetRaycastPreset(self, label): | 143 | def SetRaycastPreset(self, label): |
133 | path = os.path.join(RAYCASTING_PRESETS_DIRECTORY, label + '.plist') | 144 | path = os.path.join(RAYCASTING_PRESETS_DIRECTORY, label + '.plist') |
@@ -187,9 +198,10 @@ class Project(object): | @@ -187,9 +198,10 @@ class Project(object): | ||
187 | elif key == 'presets': | 198 | elif key == 'presets': |
188 | filepath = os.path.split(project[key]["#plist"])[-1] | 199 | filepath = os.path.split(project[key]["#plist"])[-1] |
189 | path = os.path.join(dirpath, filepath) | 200 | path = os.path.join(dirpath, filepath) |
190 | - preset = Presets() | ||
191 | - preset.OpenPlist(path) | ||
192 | - self.presets = preset | 201 | + p = Presets() |
202 | + p.OpenPlist(path) | ||
203 | + p.Test() | ||
204 | + self.presets = p | ||
193 | elif key == 'mask_dict': | 205 | elif key == 'mask_dict': |
194 | self.mask_dict = {} | 206 | self.mask_dict = {} |
195 | for mask in project[key]: | 207 | for mask in project[key]: |
@@ -210,13 +222,6 @@ class Project(object): | @@ -210,13 +222,6 @@ class Project(object): | ||
210 | setattr(self, key, project[key]) | 222 | setattr(self, key, project[key]) |
211 | print "depois", self.__dict__ | 223 | print "depois", self.__dict__ |
212 | 224 | ||
213 | - #masks = project['masks'] | ||
214 | - #for index in masks: | ||
215 | - # self.mask_dict[index] = masks[index] | ||
216 | - | ||
217 | - #surfaces = project['surfaces'] | ||
218 | - #for index in surfaces: | ||
219 | - # self.surface_dict[index] = surfaces[index] | ||
220 | 225 | ||
221 | 226 | ||
222 | def Compress(folder, filename): | 227 | def Compress(folder, filename): |