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 | 138 | def LoadProject(self): |
139 | 139 | proj = prj.Project() |
140 | 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 | 146 | self.LoadImagedataInfo() # TODO: where do we insert this <<<? |
143 | 147 | ps.Publisher().sendMessage('Bright and contrast adjustment image',\ |
144 | 148 | (proj.window, proj.level)) |
... | ... | @@ -172,8 +176,10 @@ class Controller(): |
172 | 176 | |
173 | 177 | proj = prj.Project() |
174 | 178 | proj.name = dicom.patient.name |
179 | + proj.modality = dicom.acquisition.modality | |
175 | 180 | proj.SetAcquisitionModality(dicom.acquisition.modality) |
176 | 181 | proj.imagedata = imagedata |
182 | + #proj.dicom = dicom | |
177 | 183 | proj.original_orientation =\ |
178 | 184 | name_to_const[dicom.image.orientation_label] |
179 | 185 | proj.window = float(dicom.image.window) |
... | ... | @@ -226,7 +232,9 @@ class Controller(): |
226 | 232 | |
227 | 233 | # Set default value into slices' default mask |
228 | 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 | 239 | def LoadRaycastingPreset(self, pubsub_evt): |
232 | 240 | label = pubsub_evt.data |
... | ... | @@ -260,4 +268,14 @@ class Controller(): |
260 | 268 | |
261 | 269 | def OnOpenProject(self, pubsub_evt): |
262 | 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 | 169 | reader = vtk.vtkXMLImageDataReader() |
170 | 170 | reader.SetFileName(filename) |
171 | 171 | # TODO: Check if the code bellow is necessary |
172 | - #reader.WholeSlicesOn() | |
172 | + reader.WholeSlicesOn() | |
173 | 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 | 182 | def View(imagedata): |
177 | 183 | viewer = vtk.vtkImageViewer() | ... | ... |
invesalius/data/slice_.py
... | ... | @@ -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 | 329 | self.imagedata = imagedata |
330 | 330 | self.extent = imagedata.GetExtent() |
331 | 331 | |
332 | 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 | 342 | mask_opacity = self.current_mask.opacity |
336 | 343 | |
... | ... | @@ -343,7 +350,17 @@ class Slice(object): |
343 | 350 | else: |
344 | 351 | blend_filter.SetOpacity(1, 0) |
345 | 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 | 360 | blend_filter.SetInput(1, imagedata_mask) |
361 | + print "******", imagedata_mask.GetScalarType() #11 | |
362 | + print "******", imagedata_bg.GetScalarType() #11 | |
363 | + print 2 | |
347 | 364 | blend_filter.SetBlendModeToNormal() |
348 | 365 | blend_filter.GetOutput().ReleaseDataFlagOn() |
349 | 366 | self.blend_filter = blend_filter |
... | ... | @@ -508,10 +525,31 @@ class Slice(object): |
508 | 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 | 550 | # create new mask instance and insert it into project |
514 | - self.CreateMask(imagedata=imagedata) | |
551 | + if create: | |
552 | + self.CreateMask(imagedata=imagedata) | |
515 | 553 | current_mask = self.current_mask |
516 | 554 | |
517 | 555 | # properties to be inserted into pipeline | ... | ... |
invesalius/data/surface.py
... | ... | @@ -100,6 +100,44 @@ class SurfaceManager(): |
100 | 100 | ps.Publisher().subscribe(self.OnChangeSurfaceName, 'Change surface name') |
101 | 101 | ps.Publisher().subscribe(self.OnShowSurface, 'Show surface') |
102 | 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 | 142 | def AddNewActor(self, pubsub_evt): |
105 | 143 | """ | ... | ... |
invesalius/data/viewer_slice.py
... | ... | @@ -746,8 +746,8 @@ class Viewer(wx.Panel): |
746 | 746 | self.interactor.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu) |
747 | 747 | |
748 | 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 | 752 | def LoadRenderers(self, image): |
753 | 753 | number_renderers = self.layout[0] * self.layout[1] |
... | ... | @@ -788,7 +788,7 @@ class Viewer(wx.Panel): |
788 | 788 | self.cursor_ = cursor |
789 | 789 | return cursor |
790 | 790 | |
791 | - def SetInput(self, imagedata): | |
791 | + def SetInput(self, imagedata, mask_dict): | |
792 | 792 | self.imagedata = imagedata |
793 | 793 | |
794 | 794 | #ren = self.ren |
... | ... | @@ -797,7 +797,7 @@ class Viewer(wx.Panel): |
797 | 797 | # Slice pipeline, to be inserted into current viewer |
798 | 798 | slice_ = sl.Slice() |
799 | 799 | if slice_.imagedata is None: |
800 | - slice_.SetInput(imagedata) | |
800 | + slice_.SetInput(imagedata, mask_dict) | |
801 | 801 | |
802 | 802 | #actor = vtk.vtkImageActor() |
803 | 803 | #actor.SetInput(slice_.GetOutput()) | ... | ... |
invesalius/gui/task_importer.py
... | ... | @@ -32,7 +32,7 @@ BTN_OPEN_PROJECT = wx.NewId() |
32 | 32 | |
33 | 33 | WILDCARD_OPEN = "InVesalius 1 project (*.promed)|*.promed|"\ |
34 | 34 | "InVesalius 2 project (*.inv)|*.inv|"\ |
35 | - "InVesalius 3 project (*.iv3)|*.iv3|"\ | |
35 | + "InVesalius 3 project (*.inv3)|*.inv3|"\ | |
36 | 36 | "All files (*.*)|*.*" |
37 | 37 | |
38 | 38 | class TaskPanel(wx.Panel): |
... | ... | @@ -177,7 +177,10 @@ class InnerTaskPanel(wx.Panel): |
177 | 177 | defaultDir=path, |
178 | 178 | defaultFile="", wildcard=WILDCARD_OPEN, |
179 | 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 | 185 | # Show the dialog and retrieve the user response. If it is the OK response, |
183 | 186 | # process the data. |
... | ... | @@ -206,9 +209,9 @@ class InnerTaskPanel(wx.Panel): |
206 | 209 | self.OnLinkOpenProject() |
207 | 210 | |
208 | 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 | 216 | def LoadProject(self, proj_name="Unnamed"): |
214 | 217 | """ | ... | ... |
invesalius/presets.py
... | ... | @@ -105,6 +105,16 @@ class Presets(): |
105 | 105 | return filename |
106 | 106 | |
107 | 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 | 55 | # TODO: Discuss when this will be used. |
56 | 56 | self.imagedata = '' |
57 | 57 | |
58 | + self.name = '' | |
59 | + #self.dicom = '' | |
60 | + self.modality = '' | |
61 | + self.original_orientation = -1 | |
62 | + | |
58 | 63 | # Masks are related to vtkImageData |
59 | 64 | self.mask_dict = {} |
60 | 65 | # Predefined threshold values |
... | ... | @@ -65,10 +70,12 @@ class Project(object): |
65 | 70 | self.level = '' |
66 | 71 | |
67 | 72 | self.presets = Presets() |
68 | - | |
73 | + self.threshold_modes = self.presets.thresh_ct | |
74 | + self.threshold_range = '' | |
75 | + | |
69 | 76 | self.original_orientation = '' |
70 | 77 | # MRI ? CT? |
71 | - self.threshold_modes = self.presets.thresh_ct | |
78 | + | |
72 | 79 | |
73 | 80 | # TODO: define how we will relate these threshold values to |
74 | 81 | # default threshold labels |
... | ... | @@ -121,13 +128,17 @@ class Project(object): |
121 | 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 | 135 | if type_ == "MRI": |
126 | 136 | self.threshold_modes = self.presets.thresh_mri |
127 | 137 | elif type_ == "CT": |
128 | 138 | self.threshold_modes = self.presets.thresh_ct |
129 | 139 | else: |
130 | 140 | print "Different Acquisition Modality!!!" |
141 | + self.modality = type_ | |
131 | 142 | |
132 | 143 | def SetRaycastPreset(self, label): |
133 | 144 | path = os.path.join(RAYCASTING_PRESETS_DIRECTORY, label + '.plist') |
... | ... | @@ -187,9 +198,10 @@ class Project(object): |
187 | 198 | elif key == 'presets': |
188 | 199 | filepath = os.path.split(project[key]["#plist"])[-1] |
189 | 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 | 205 | elif key == 'mask_dict': |
194 | 206 | self.mask_dict = {} |
195 | 207 | for mask in project[key]: |
... | ... | @@ -210,13 +222,6 @@ class Project(object): |
210 | 222 | setattr(self, key, project[key]) |
211 | 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 | 227 | def Compress(folder, filename): | ... | ... |