Commit 3174c58fe17f8eb04ad9817ad20cce8b8cde4896

Authored by tatiana
1 parent 63ad0eb3

ADD: Preview DICOM in import panel (still working)

invesalius/control.py
... ... @@ -39,9 +39,12 @@ class Controller():
39 39  
40 40 # retrieve DICOM files splited into groups
41 41 patient_series = dcm.GetDicomGroups(path)
42   - ps.Publisher().sendMessage("Load import panel", patient_series)
43   - first_patient = patient_series[0]
44   - #ps.Publisher().sendMessage("Load dicom preview", first_patient)
  42 + if patient_series:
  43 + ps.Publisher().sendMessage("Load import panel", patient_series)
  44 + first_patient = patient_series[0]
  45 + ps.Publisher().sendMessage("Load dicom preview", first_patient)
  46 + else:
  47 + print "No DICOM files on directory"
45 48  
46 49 def OnImportMedicalImages(self, pubsub_evt):
47 50 directory = pubsub_evt.data
... ... @@ -144,103 +147,6 @@ class Controller():
144 147  
145 148 return imagedata, dicom
146 149  
147   - def ImportDirectory(self, pubsub_evt=None, dir_=None):
148   - """
149   - Import medical images (if any) and generate vtkImageData, saving data
150   - inside Project instance.
151   - """
152   -
153   - if not dir_:
154   - dir_ = pubsub_evt.data
155   -
156   - # Select medical images from directory and generate vtkImageData
157   - output = dcm.LoadImages(dir_)
158   - proj = prj.Project()
159   - proj.name = "Untitled"
160   -
161   - if output:
162   - # In this case, there were DICOM files on the folder
163   - imagedata, dicom = output
164   -
165   - # Set orientation
166   - orientation = dicom.image.orientation_label
167   - if (orientation == "CORONAL"):
168   - orientation = const.CORONAL
169   - elif(orientation == "SAGITTAL"):
170   - orientation = const.SAGITAL
171   - else:
172   - orientation = const.AXIAL
173   -
174   - # Retrieve window, level, modalit
175   - window = float(dicom.image.window)
176   - level = float(dicom.image.level)
177   - acquisition_modality = dicom.acquisition.modality
178   -
179   - # If there was gantry tilt, fix it:
180   - tilt_value = dicom.acquisition.tilt
181   - if (tilt_value):
182   - # Tell user gantry tilt and fix, according to answer
183   - message = "Fix gantry tilt applying the degrees bellow"
184   - value = -1*tilt_value
185   - tilt_value = dialog.ShowNumberDialog(message, value)
186   - imagedata = utils.FixGantryTilt(imagedata, tilt_value)
187   - else:
188   - "No DICOM files were found. Trying to read with ITK..."
189   - imagedata = analyze.ReadDirectory(dir_)
190   - if imagedata:
191   - acquisition_modality = "MRI"
192   -
193   - #TODO: Verify if all Analyse is AXIAL orientation
194   - orientation = const.AXIAL
195   -
196   - proj.SetAcquisitionModality(acquisition_modality)
197   - proj.imagedata = imagedata
198   - proj.original_orientation = orientation
199   - threshold_range = proj.imagedata.GetScalarRange()
200   - proj.window = window = threshold_range[1] - threshold_range[0]
201   - proj.level = level = (0.5 * (threshold_range[1] + threshold_range[0]))
202   -
203   - ps.Publisher().sendMessage('Update window level value',\
204   - (proj.window, proj.level))
205   -
206   - if not imagedata:
207   - print "Sorry, but there are no medical images supported on this dir."
208   - else:
209   - # Create new project
210   - proj.SetAcquisitionModality(acquisition_modality)
211   - proj.imagedata = imagedata
212   - proj.original_orientation = orientation
213   - proj.window = window
214   - proj.level = level
215   -
216   - threshold_range = proj.imagedata.GetScalarRange()
217   -
218   - const.WINDOW_LEVEL['Default'] = (window, level)
219   - const.WINDOW_LEVEL['Manual'] = (window, level)
220   -
221   - const.THRESHOLD_OUTVALUE = threshold_range[0]
222   - const.THRESHOLD_INVALUE = threshold_range[1]
223   -
224   - # Based on imagedata, load data to GUI
225   - ps.Publisher().sendMessage('Load slice to viewer', (imagedata))
226   -
227   - # TODO: where to insert!!!
228   - self.LoadImagedataInfo()
229   -
230   - #Initial Window and Level
231   - ps.Publisher().sendMessage('Bright and contrast adjustment image',\
232   - (proj.window, proj.level))
233   -
234   - ps.Publisher().sendMessage('Update window level value',\
235   - (proj.window, proj.level))
236   -
237   - # Call frame so it shows slice and volume related panels
238   - ps.Publisher().sendMessage('Show content panel')
239   -
240   - ps.Publisher().sendMessage('Update AUI')
241   -
242   - ps.Publisher().sendMessage('Load slice plane')
243   -
244 150 def LoadImagedataInfo(self):
245 151 proj = prj.Project()
246 152  
... ...
invesalius/gui/dicom_preview_panel.py
1 1 #!/usr/bin/env python
2 2 # -*- coding: UTF-8 -*-
3 3  
  4 +#TODO: To create a beautiful API
4 5 import wx
5 6 import vtk
6 7 import vtkgdcm
7 8  
8 9 from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
9   -#from reader import dicom_reader
  10 +from reader import dicom_reader
10 11  
11 12 myEVT_SELECT = wx.NewEventType()
12 13 # This event occurs when the user select a preview
... ... @@ -31,66 +32,10 @@ class SerieEvent(PreviewEvent):
31 32 def __init__(self , evtType, id):
32 33 super(SerieEvent, self).__init__(evtType, id)
33 34  
34   -class DicomImageData(object):
35   - def __init__(self):
36   - pass
37   -
38   - def SetInput(self, dicom):
39   - reader = vtkgdcm.vtkGDCMImageReader()
40   - reader.SetFileName(dicom.image.file)
41   - imagedata = reader.GetOutput()
42   -
43   - scale = imagedata.GetScalarRange()
44   -
45   - cast = vtk.vtkImageMapToWindowLevelColors()
46   - cast.SetInput(imagedata)
47   - cast.SetWindow(float(dicom.image.window))
48   - cast.SetLevel(float(dicom.image.level))
49   -
50   - self.imagedata = cast.GetOutput()
51   -
52   - def GetOutput(self):
53   - return self.imagedata
54   -
55   -
56   -class DicomLoader(object):
57   - """
58   - Responsible for load dicom files. A dictionary like behavior
59   - """
60   - def __init__(self):
61   - self.loaded_dicoms = {}
62   -
63   - def __getitem__(self, filename):
64   - """
65   - Especial method to behave like dictionary
66   - """
67   - try:
68   - return self.loaded_dicoms[filename]
69   - except KeyError:
70   - #print "Except"
71   - self._load_dicom_files(filename)
72   - return self.loaded_dicoms[filename]
73   -
74   - def _load_dicom_files(self, filename, window=150, level=230):
75   - reader = vtkgdcm.vtkGDCMImageReader()
76   - reader.SetFileName(filename)
77   - imagedata = reader.GetOutput()
78   -
79   - scale = imagedata.GetScalarRange()
80   -
81   - cast = vtk.vtkImageMapToWindowLevelColors()
82   - cast.SetInput(imagedata)
83   - cast.SetWindow(float(window))
84   - cast.SetLevel(float(level))
85   -
86   - self.loaded_dicoms[filename] = cast.GetOutput()
87   -
88   -
89 35 class Preview(wx.Panel):
90 36 """
91 37 Where the images will be showed.
92 38 """
93   - dicom_loader = DicomLoader()
94 39 def __init__(self, parent):
95 40 super(Preview, self).__init__(parent)
96 41 # Will it be white?
... ... @@ -140,29 +85,40 @@ class Preview(wx.Panel):
140 85 def SetSubtitle(self, subtitle):
141 86 self.subtitle.SetLabel(subtitle)
142 87  
143   - def SetGroup(self, group):
144   - self.SetTitle(group.title)
145   - self.SetSubtitle("%d images"%(group.nslices))
146   - d = DicomImageData()
147   - d.SetInput(group.dicom)
148   - imagedata = d.GetOutput()
149   - self.actor.SetInput(imagedata)
150   - self.render.ResetCamera()
151   -
152   - def SetImage(self, image_data):
  88 + def SetImage(self, image_file):
153 89 """
154 90 Set a Image to preview.
155 91 """
156   - filename, window, level, title, subtitle = image_data
157   - print image_data
158   - self.SetTitle(title)
159   - self.SetSubtitle(subtitle)
160   - #self.ID = image_file[5] # todo: check if this is necessary
  92 + self.SetTitle(image_file[3])
  93 + self.SetSubtitle(image_file[4])
  94 + self.ID = image_file[5]
  95 +
  96 + image_reader = vtkgdcm.vtkGDCMImageReader()
  97 + image_reader.SetFileName(image_file[0])
  98 + image = image_reader.GetOutput()
  99 +
  100 + scale = image.GetScalarRange()
  101 +
  102 + cast = vtk.vtkImageMapToWindowLevelColors()
  103 + #cast.SetShift(abs(scale[0]))
  104 + #cast.SetScale(255.0/(scale[1] - scale[0]))
  105 + #cast.ClampOverflowOn()
  106 + cast.SetInput(image)
  107 + #cast.SetOutputScalarTypeToUnsignedChar()
  108 + try:
  109 + window = float(image_file[1])
  110 + level = float(image_file[2])
  111 + except TypeError:
  112 + #TODO: These values are good?
  113 + level = 230
  114 + window = 150
161 115  
162   - # TODO: enhace interface
163   - imagedata = Preview.dicom_loader[filename]
164   - self.actor.SetInput(imagedata)
  116 + cast.SetWindow(window)
  117 + cast.SetLevel(level)
  118 + self.actor.SetInput(cast.GetOutput())
165 119 self.render.ResetCamera()
  120 + #self.interactor.Render()
  121 +
166 122  
167 123 class DicomPreviewSeries(wx.Panel):
168 124 """A dicom series preview panel"""
... ... @@ -173,6 +129,7 @@ class DicomPreviewSeries(wx.Panel):
173 129 self.sizer = wx.BoxSizer(wx.HORIZONTAL)
174 130 self.SetSizer(self.sizer)
175 131 self.displayed_position = 0
  132 + self.files = []
176 133 self._init_ui()
177 134  
178 135 def _init_ui(self):
... ... @@ -202,54 +159,59 @@ class DicomPreviewSeries(wx.Panel):
202 159 my_evt.SetSelectedID(evt.GetSelectID())
203 160 self.GetEventHandler().ProcessEvent(my_evt)
204 161  
205   - def SetDicomDirectory(self, directory):
206   - print "SetDicomDirectory"
  162 + def SetPatientGroups(self, patient):
  163 + group_list = patient.GetGroups()
  164 + n = 0
  165 + for group in group_list:
  166 + info = (group.dicom.image.file,
  167 + float(group.dicom.image.window),
  168 + float(group.dicom.image.level),
  169 + group.title,
  170 + "%d Images" %(group.nslices),
  171 + n)
  172 + self.files.append(info)
  173 + n+=1
  174 +
  175 + scroll_range = len(self.files)/5
  176 + if scroll_range * 5 < len(self.files):
  177 + scroll_range +=1
  178 + self.scroll.SetScrollbar(0, 3, scroll_range, 5)
  179 +
  180 + self._Display_Previews()
  181 +
  182 +
  183 + def SetDicomDirectoryOld(self, directory):
  184 + import time
  185 + a = time.time()
207 186 self.directory = directory
208 187 self.series = dicom_reader.GetSeries(directory)[0]
209   - print "keys", [key[0] for key in self.series.keys()]
210   -
211   - s = self.series
212   - for k in s.keys():
213   - print "------ PESSOA ---------"
214   - print "%s (%d series)"%(k[0], len(s[k])-1)
215   - for ns in range(1,len(s[k])):
216   - print "------ SERIE ---------"
217   - print "unnamed"
218   - print "age %s" %(s[k][ns][8])
219   - print "date acquired %s %s" %(s[k][ns][0], s[k][ns][4])
220   - print "birthdate %s" %(s[k][ns][23])
221   - print "institution %s" %(s[k][ns][6])
222   -
  188 + b = time.time()
223 189 # TODO: I need to improve this
224 190 self.files = [(self.series[i][0][0][8], # Filename
225 191 self.series[i][0][0][12], # Window Level
226 192 self.series[i][0][0][13], # Window Width
227   - "unnamed", #% (n + 1), # Title
  193 + "Serie %d" % (n + 1), # Title
228 194 "%d Images" % len(self.series[i][0]), # Subtitle
229   - i) for n, i in enumerate(self.series)]
  195 + n) for n, i in enumerate(self.series)]
230 196  
231   - def SetDicomSeries(self, patient):
232   - #self.files = files
233   - ngroups = patient.ngroups
234   - self.groups = patient.GetGroups()
235   -
236   - scroll_range = ngroups/5
237   - if scroll_range * 5 < ngroups:
  197 + scroll_range = len(self.files)/5
  198 + if scroll_range * 5 < len(self.files):
238 199 scroll_range +=1
239 200 self.scroll.SetScrollbar(0, 3, scroll_range, 5)
240   - self._display_previews()
241 201  
242   - def _display_previews(self):
243   - begin = self.displayed_position * 5
244   - end = begin + 15
245   - for group, preview in zip(self.groups[begin:end], self.previews):
246   - preview.SetGroup(group)
247   - preview.Show()
  202 + self._Display_Previews()
  203 +
  204 + def _Display_Previews(self):
  205 + initial = self.displayed_position * 5
  206 + final = initial + 15
  207 + for f, p in zip(self.files[initial:final], self.previews):
  208 + p.SetImage(f)
  209 + p.Show()
248 210  
249 211 def OnScroll(self, evt):
250 212 self.displayed_position = evt.GetPosition()
251 213 [i.Hide() for i in self.previews]
252   - self._display_previews()
  214 + self._Display_Previews()
253 215  
254 216  
255 217 class DicomPreview(wx.Panel):
... ... @@ -261,7 +223,7 @@ class DicomPreview(wx.Panel):
261 223 self.sizer = wx.BoxSizer(wx.HORIZONTAL)
262 224 self.SetSizer(self.sizer)
263 225 self.displayed_position = 0
264   - self.nhidden_last_display = 0
  226 + self.files = []
265 227 self._init_ui()
266 228  
267 229 def _init_ui(self):
... ... @@ -277,7 +239,7 @@ class DicomPreview(wx.Panel):
277 239 for i in xrange(3):
278 240 for j in xrange(5):
279 241 p = Preview(self)
280   - #p.Hide()
  242 + p.Hide()
281 243 self.previews.append(p)
282 244 self.grid.Add(p, i, j)
283 245  
... ... @@ -289,47 +251,55 @@ class DicomPreview(wx.Panel):
289 251 self.directory = directory
290 252 self.series = dicom_reader.GetSeries(directory)[0]
291 253  
292   - def SetDicomSerie(self, serie):
293   - k = serie
  254 + def SetPatientGroups(self, patient):
  255 + self.group_list = patient.GetGroups()
  256 +
  257 + def SetDicomSerie(self, pos):
  258 + group = self.group_list[pos]
  259 + #dicom_files = group.GetList()
  260 + dicom_files = group.GetHandSortedList()
  261 + n = 0
  262 + for dicom in dicom_files:
  263 + info = (dicom.image.file,
  264 + dicom.image.window,
  265 + dicom.image.level,
  266 + "Image %d" % (dicom.image.number),
  267 + "%.2f" % (dicom.image.position[2]),
  268 + n)
  269 + self.files.append(info)
  270 + n+=1
  271 +
  272 + scroll_range = len(self.files)/5
  273 + if scroll_range * 5 < len(self.files):
  274 + scroll_range +=1
  275 + self.scroll.SetScrollbar(0, 3, scroll_range, 5)
  276 + self._Display_Previews()
  277 +
  278 + def SetDicomSerieOld(self, serie):
  279 + k = self.series.keys()[serie]
294 280 self.files = [(i[8],
295 281 i[12],
296 282 i[13],
297   - "Image %d" % (n + 1), # Title
298   - "%s"% str(i[3][2]), # Spacing
299   - n)for n, i in enumerate(self.series[k][0])]
  283 + "Serie %d" % (n + 1), # Title
  284 + "%d Images" % n, # Subtitle
  285 + n)for n, i in enumerate(self.series[k][0])]
300 286 scroll_range = len(self.files)/5
301 287 if scroll_range * 5 < len(self.files):
302 288 scroll_range +=1
303 289 self.scroll.SetScrollbar(0, 3, scroll_range, 5)
304   - self._display_previews()
  290 + self._Display_Previews()
305 291  
306   - def _display_previews(self):
  292 + def _Display_Previews(self):
307 293 initial = self.displayed_position * 5
308 294 final = initial + 15
309   -
310   - if len(self.files) < final:
311   - for i in xrange(final-len(self.files)):
312   - try:
313   - self.previews[-i-1].Hide()
314   - except IndexError:
315   - #print "doesn't exist!"
316   - pass
317   - self.nhidden_last_display = final-len(self.files)
318   - else:
319   - if self.nhidden_last_display:
320   - for i in xrange(self.nhidden_last_display):
321   - try:
322   - self.previews[-i-1].Show()
323   - except IndexError:
324   - #print "doesn't exist!"
325   - pass
326   - self.nhidden_last_display = 0
327   -
328 295 for f, p in zip(self.files[initial:final], self.previews):
329 296 p.SetImage(f)
330   - p.interactor.Render()
  297 + p.Show()
331 298  
332 299 def OnScroll(self, evt):
333   - if self.displayed_position != evt.GetPosition():
334   - self.displayed_position = evt.GetPosition()
335   - self._display_previews()
  300 + self.displayed_position = evt.GetPosition()
  301 + [i.Hide() for i in self.previews]
  302 + self._Display_Previews()
  303 + self.Update()
  304 + self.Update()
  305 +
... ...
invesalius/gui/import_panel.py
... ... @@ -153,7 +153,7 @@ class TextPanel(wx.Panel):
153 153 class ImagePanel(wx.Panel):
154 154 def __init__(self, parent):
155 155 wx.Panel.__init__(self, parent, -1)
156   - self.SetBackgroundColour((0,255,0))
  156 + #self.SetBackgroundColour((0,255,0))
157 157  
158 158 splitter = spl.MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE)
159 159 splitter.SetOrientation(wx.HORIZONTAL)
... ... @@ -172,19 +172,48 @@ class ImagePanel(wx.Panel):
172 172 class SeriesPanel(wx.Panel):
173 173 def __init__(self, parent):
174 174 wx.Panel.__init__(self, parent, -1)
175   - self.SetBackgroundColour((0,0,0))
  175 + #self.SetBackgroundColour((0,0,0))
  176 +
176 177 self.serie_preview = dpp.DicomPreviewSeries(self)
  178 + self.dicom_preview = dpp.DicomPreview(self)
  179 + self.dicom_preview.Show(0)
  180 +
  181 + self.sizer = wx.BoxSizer(wx.VERTICAL)
  182 + self.sizer.Add(self.serie_preview, 1, wx.EXPAND | wx.ALL, 5)
  183 + self.sizer.Add(self.dicom_preview, 1, wx.EXPAND | wx.ALL, 5)
  184 + self.sizer.Fit(self)
  185 +
  186 + self.SetSizer(self.sizer)
  187 + self.SetAutoLayout(True)
  188 + self.Show()
  189 +
177 190  
178 191 self.__bind_evt()
  192 + self._bind_gui_evt()
179 193  
180 194 def __bind_evt(self):
181 195 ps.Publisher().subscribe(self.ShowDicomSeries, "Load dicom preview")
182 196  
  197 + def _bind_gui_evt(self):
  198 + self.Bind(dpp.EVT_SELECT_SERIE, self.OnSelectSerie)
  199 +
  200 + def OnSelectSerie(self, evt):
  201 + serie = evt.GetSelectID()
  202 + self.dicom_preview.SetDicomSerie(serie)
  203 +
  204 + self.dicom_preview.Show(1)
  205 + #self.sizer.Detach(self.serie_preview)
  206 + self.serie_preview.Show(0)
  207 + self.sizer.Layout()
  208 + #self.Show()
  209 + self.Update()
  210 +
  211 +
183 212 def ShowDicomSeries(self, pubsub_evt):
184 213 print "---- ShowDicomSeries ----"
185   - list_dicom = pubsub_evt.data
186   - print list_dicom
187   - self.serie_preview.SetDicomSeries(list_dicom)
  214 + first_patient = pubsub_evt.data
  215 + self.serie_preview.SetPatientGroups(first_patient)
  216 + self.dicom_preview.SetPatientGroups(first_patient)
188 217  
189 218  
190 219  
... ...
invesalius/invesalius.py
... ... @@ -43,7 +43,7 @@ class InVesalius(wx.App):
43 43 def OnInit(self):
44 44 self.main = Frame(None)
45 45 self.control = Controller(self.main)
46   - self.SetAppName("InVesalius 3.0")
  46 + self.SetAppName("InVesalius 3")
47 47 return True
48 48  
49 49 def ShowFrame(self):
... ...