Commit bc21685fee9a79071c8678b8792739b3e6c722b5
1 parent
2faf0f45
Exists in
master
and in
68 other branches
ADD: ProgressDialog in the loading serie
Showing
5 changed files
with
123 additions
and
16 deletions
Show diff stats
invesalius/control.py
| @@ -51,8 +51,9 @@ class Controller(): | @@ -51,8 +51,9 @@ class Controller(): | ||
| 51 | #self.frame.Bind(reader.evt_end_load_file, self.LoadPanel) | 51 | #self.frame.Bind(reader.evt_end_load_file, self.LoadPanel) |
| 52 | 52 | ||
| 53 | def Progress(self, evt): | 53 | def Progress(self, evt): |
| 54 | - print evt | ||
| 55 | data = evt.data | 54 | data = evt.data |
| 55 | + if (data): | ||
| 56 | + message = "Loading file %d of %d"%(data[0],data[1]) | ||
| 56 | 57 | ||
| 57 | if (data): | 58 | if (data): |
| 58 | if not(self.progress_dialog): | 59 | if not(self.progress_dialog): |
| @@ -60,7 +61,7 @@ class Controller(): | @@ -60,7 +61,7 @@ class Controller(): | ||
| 60 | maximum = data[1]) | 61 | maximum = data[1]) |
| 61 | else: | 62 | else: |
| 62 | print data[0] | 63 | print data[0] |
| 63 | - if not(self.progress_dialog.Update(data[0])): | 64 | + if not(self.progress_dialog.Update(data[0],message)): |
| 64 | self.progress_dialog.Close() | 65 | self.progress_dialog.Close() |
| 65 | self.progress_dialog = None | 66 | self.progress_dialog = None |
| 66 | else: | 67 | else: |
| @@ -153,7 +154,7 @@ class Controller(): | @@ -153,7 +154,7 @@ class Controller(): | ||
| 153 | 154 | ||
| 154 | def OnOpenDicomGroup(self, pubsub_evt): | 155 | def OnOpenDicomGroup(self, pubsub_evt): |
| 155 | group = pubsub_evt.data | 156 | group = pubsub_evt.data |
| 156 | - imagedata, dicom = self.OpenDicomGroup(group, gui=False) | 157 | + imagedata, dicom = self.OpenDicomGroup(group, gui=True) |
| 157 | self.CreateDicomProject(imagedata, dicom) | 158 | self.CreateDicomProject(imagedata, dicom) |
| 158 | self.LoadProject() | 159 | self.LoadProject() |
| 159 | 160 |
invesalius/data/imagedata_utils.py
| 1 | import math | 1 | import math |
| 2 | import vtk | 2 | import vtk |
| 3 | import vtkgdcm | 3 | import vtkgdcm |
| 4 | +import wx.lib.pubsub as ps | ||
| 4 | 5 | ||
| 5 | import constants as const | 6 | import constants as const |
| 7 | +from data import vtk_utils | ||
| 8 | + | ||
| 6 | 9 | ||
| 7 | # TODO: Test cases which are originally in sagittal/coronal orientation | 10 | # TODO: Test cases which are originally in sagittal/coronal orientation |
| 8 | # and have gantry | 11 | # and have gantry |
| @@ -27,7 +30,8 @@ def ResampleImage3D(imagedata, value): | @@ -27,7 +30,8 @@ def ResampleImage3D(imagedata, value): | ||
| 27 | 30 | ||
| 28 | return resample.GetOutput() | 31 | return resample.GetOutput() |
| 29 | 32 | ||
| 30 | -def ResampleImage2D(imagedata, xy_dimension): | 33 | +def ResampleImage2D(imagedata, xy_dimension, |
| 34 | + update_progress = None): | ||
| 31 | """ | 35 | """ |
| 32 | Resample vtkImageData matrix. | 36 | Resample vtkImageData matrix. |
| 33 | """ | 37 | """ |
| @@ -56,6 +60,10 @@ def ResampleImage2D(imagedata, xy_dimension): | @@ -56,6 +60,10 @@ def ResampleImage2D(imagedata, xy_dimension): | ||
| 56 | resample.SetAxisMagnificationFactor(0, factor) | 60 | resample.SetAxisMagnificationFactor(0, factor) |
| 57 | resample.SetAxisMagnificationFactor(1, factor) | 61 | resample.SetAxisMagnificationFactor(1, factor) |
| 58 | resample.SetOutputSpacing(spacing[0] * factor, spacing[1] * factor, spacing[2]) | 62 | resample.SetOutputSpacing(spacing[0] * factor, spacing[1] * factor, spacing[2]) |
| 63 | + if (update_progress): | ||
| 64 | + message = "Generating multiplanar visualization..." | ||
| 65 | + resample.AddObserver("ProgressEvent", lambda obj, | ||
| 66 | + evt:update_progress(resample,message)) | ||
| 59 | resample.Update() | 67 | resample.Update() |
| 60 | 68 | ||
| 61 | 69 | ||
| @@ -167,14 +175,18 @@ def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf): | @@ -167,14 +175,18 @@ def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf): | ||
| 167 | return voi.GetOutput() | 175 | return voi.GetOutput() |
| 168 | 176 | ||
| 169 | def CreateImageData(filelist, zspacing): | 177 | def CreateImageData(filelist, zspacing): |
| 170 | - | 178 | + message = "Generating multiplanar visualization..." |
| 171 | if not(const.REDUCE_IMAGEDATA_QUALITY): | 179 | if not(const.REDUCE_IMAGEDATA_QUALITY): |
| 180 | + update_progress= vtk_utils.ShowProgress(1) | ||
| 181 | + | ||
| 172 | array = vtk.vtkStringArray() | 182 | array = vtk.vtkStringArray() |
| 173 | for x in xrange(len(filelist)): | 183 | for x in xrange(len(filelist)): |
| 174 | array.InsertValue(x,filelist[x]) | 184 | array.InsertValue(x,filelist[x]) |
| 175 | - | 185 | + |
| 176 | reader = vtkgdcm.vtkGDCMImageReader() | 186 | reader = vtkgdcm.vtkGDCMImageReader() |
| 177 | reader.SetFileNames(array) | 187 | reader.SetFileNames(array) |
| 188 | + reader.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 189 | + update_progress(reader,message)) | ||
| 178 | reader.Update() | 190 | reader.Update() |
| 179 | 191 | ||
| 180 | # The zpacing is a DicomGroup property, so we need to set it | 192 | # The zpacing is a DicomGroup property, so we need to set it |
| @@ -183,6 +195,9 @@ def CreateImageData(filelist, zspacing): | @@ -183,6 +195,9 @@ def CreateImageData(filelist, zspacing): | ||
| 183 | spacing = imagedata.GetSpacing() | 195 | spacing = imagedata.GetSpacing() |
| 184 | imagedata.SetSpacing(spacing[0], spacing[1], zspacing) | 196 | imagedata.SetSpacing(spacing[0], spacing[1], zspacing) |
| 185 | else: | 197 | else: |
| 198 | + update_progress= vtk_utils.ShowProgress(2*len(filelist), | ||
| 199 | + dialog_type = "ProgressDialog") | ||
| 200 | + | ||
| 186 | # Reformat each slice and future append them | 201 | # Reformat each slice and future append them |
| 187 | appender = vtk.vtkImageAppend() | 202 | appender = vtk.vtkImageAppend() |
| 188 | appender.SetAppendAxis(2) #Define Stack in Z | 203 | appender.SetAppendAxis(2) #Define Stack in Z |
| @@ -194,13 +209,16 @@ def CreateImageData(filelist, zspacing): | @@ -194,13 +209,16 @@ def CreateImageData(filelist, zspacing): | ||
| 194 | # If the resolution of the matrix is too large | 209 | # If the resolution of the matrix is too large |
| 195 | reader = vtkgdcm.vtkGDCMImageReader() | 210 | reader = vtkgdcm.vtkGDCMImageReader() |
| 196 | reader.SetFileName(filelist[x]) | 211 | reader.SetFileName(filelist[x]) |
| 212 | + reader.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 213 | + update_progress(reader,message)) | ||
| 197 | reader.Update() | 214 | reader.Update() |
| 198 | 215 | ||
| 199 | #Resample image in x,y dimension | 216 | #Resample image in x,y dimension |
| 200 | - slice_imagedata = ResampleImage2D(reader.GetOutput(), 256) | 217 | + slice_imagedata = ResampleImage2D(reader.GetOutput(), 256, update_progress) |
| 201 | 218 | ||
| 202 | #Stack images in Z axes | 219 | #Stack images in Z axes |
| 203 | appender.AddInput(slice_imagedata) | 220 | appender.AddInput(slice_imagedata) |
| 221 | + #appender.AddObserver("ProgressEvent", lambda obj,evt:update_progress(appender)) | ||
| 204 | appender.Update() | 222 | appender.Update() |
| 205 | 223 | ||
| 206 | # The zpacing is a DicomGroup property, so we need to set it | 224 | # The zpacing is a DicomGroup property, so we need to set it |
| @@ -210,7 +228,78 @@ def CreateImageData(filelist, zspacing): | @@ -210,7 +228,78 @@ def CreateImageData(filelist, zspacing): | ||
| 210 | 228 | ||
| 211 | imagedata.SetSpacing(spacing[0], spacing[1], zspacing) | 229 | imagedata.SetSpacing(spacing[0], spacing[1], zspacing) |
| 212 | 230 | ||
| 231 | + imagedata.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 232 | + update_progress(imagedata,message)) | ||
| 213 | imagedata.Update() | 233 | imagedata.Update() |
| 234 | + | ||
| 214 | return imagedata | 235 | return imagedata |
| 215 | 236 | ||
| 216 | 237 | ||
| 238 | +class ImageCreator: | ||
| 239 | + def __init__(self): | ||
| 240 | + ps.Publisher().sendMessage("Cancel imagedata load", self.CancelImageDataLoad) | ||
| 241 | + | ||
| 242 | + def CancelImageDataLoad(self, evt_pusub): | ||
| 243 | + self.running = evt_pusub.data | ||
| 244 | + | ||
| 245 | + def CreateImageData(filelist, zspacing): | ||
| 246 | + message = "Generating multiplanar visualization..." | ||
| 247 | + if not(const.REDUCE_IMAGEDATA_QUALITY): | ||
| 248 | + update_progress= vtk_utils.ShowProgress(1) | ||
| 249 | + | ||
| 250 | + array = vtk.vtkStringArray() | ||
| 251 | + for x in xrange(len(filelist)): | ||
| 252 | + array.InsertValue(x,filelist[x]) | ||
| 253 | + | ||
| 254 | + reader = vtkgdcm.vtkGDCMImageReader() | ||
| 255 | + reader.SetFileNames(array) | ||
| 256 | + reader.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 257 | + update_progress(reader,message)) | ||
| 258 | + reader.Update() | ||
| 259 | + | ||
| 260 | + # The zpacing is a DicomGroup property, so we need to set it | ||
| 261 | + imagedata = vtk.vtkImageData() | ||
| 262 | + imagedata.DeepCopy(reader.GetOutput()) | ||
| 263 | + spacing = imagedata.GetSpacing() | ||
| 264 | + imagedata.SetSpacing(spacing[0], spacing[1], zspacing) | ||
| 265 | + else: | ||
| 266 | + update_progress= vtk_utils.ShowProgress(2*len(filelist), | ||
| 267 | + dialog_type = "ProgressDialog") | ||
| 268 | + | ||
| 269 | + # Reformat each slice and future append them | ||
| 270 | + appender = vtk.vtkImageAppend() | ||
| 271 | + appender.SetAppendAxis(2) #Define Stack in Z | ||
| 272 | + | ||
| 273 | + # Reformat each slice | ||
| 274 | + for x in xrange(len(filelist)): | ||
| 275 | + # TODO: We need to check this automatically according | ||
| 276 | + # to each computer's architecture | ||
| 277 | + # If the resolution of the matrix is too large | ||
| 278 | + reader = vtkgdcm.vtkGDCMImageReader() | ||
| 279 | + reader.SetFileName(filelist[x]) | ||
| 280 | + reader.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 281 | + update_progress(reader,message)) | ||
| 282 | + reader.Update() | ||
| 283 | + | ||
| 284 | + #Resample image in x,y dimension | ||
| 285 | + slice_imagedata = ResampleImage2D(reader.GetOutput(), 256, update_progress) | ||
| 286 | + | ||
| 287 | + #Stack images in Z axes | ||
| 288 | + appender.AddInput(slice_imagedata) | ||
| 289 | + #appender.AddObserver("ProgressEvent", lambda obj,evt:update_progress(appender)) | ||
| 290 | + appender.Update() | ||
| 291 | + | ||
| 292 | + # The zpacing is a DicomGroup property, so we need to set it | ||
| 293 | + imagedata = vtk.vtkImageData() | ||
| 294 | + imagedata.DeepCopy(appender.GetOutput()) | ||
| 295 | + spacing = imagedata.GetSpacing() | ||
| 296 | + | ||
| 297 | + imagedata.SetSpacing(spacing[0], spacing[1], zspacing) | ||
| 298 | + | ||
| 299 | + imagedata.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 300 | + update_progress(imagedata,message)) | ||
| 301 | + imagedata.Update() | ||
| 302 | + | ||
| 303 | + return imagedata | ||
| 304 | + | ||
| 305 | + |
invesalius/data/vtk_utils.py
| 1 | import wx.lib.pubsub as ps | 1 | import wx.lib.pubsub as ps |
| 2 | import vtk | 2 | import vtk |
| 3 | 3 | ||
| 4 | + | ||
| 4 | import constants as const | 5 | import constants as const |
| 6 | +from gui.dialogs import ProgressDialog | ||
| 5 | 7 | ||
| 6 | # If you are frightened by the code bellow, or think it must have been result of | 8 | # If you are frightened by the code bellow, or think it must have been result of |
| 7 | # an identation error, lookup at: | 9 | # an identation error, lookup at: |
| @@ -13,7 +15,8 @@ import constants as const | @@ -13,7 +15,8 @@ import constants as const | ||
| 13 | # http://www.ibm.com/developerworks/library/l-prog2.html | 15 | # http://www.ibm.com/developerworks/library/l-prog2.html |
| 14 | # http://jjinux.blogspot.com/2006/10/python-modifying-counter-in-closure.html | 16 | # http://jjinux.blogspot.com/2006/10/python-modifying-counter-in-closure.html |
| 15 | 17 | ||
| 16 | -def ShowProgress(number_of_filters = 1): | 18 | +def ShowProgress(number_of_filters = 1, |
| 19 | + dialog_type="GaugeProgress"): | ||
| 17 | """ | 20 | """ |
| 18 | To use this closure, do something like this: | 21 | To use this closure, do something like this: |
| 19 | UpdateProgress = ShowProgress(NUM_FILTERS) | 22 | UpdateProgress = ShowProgress(NUM_FILTERS) |
| @@ -21,10 +24,13 @@ def ShowProgress(number_of_filters = 1): | @@ -21,10 +24,13 @@ def ShowProgress(number_of_filters = 1): | ||
| 21 | """ | 24 | """ |
| 22 | progress = [0] | 25 | progress = [0] |
| 23 | last_obj_progress = [0] | 26 | last_obj_progress = [0] |
| 27 | + if (dialog_type == "ProgressDialog"): | ||
| 28 | + dlg = ProgressDialog(100) | ||
| 29 | + | ||
| 24 | 30 | ||
| 25 | # when the pipeline is larger than 1, we have to consider this object | 31 | # when the pipeline is larger than 1, we have to consider this object |
| 26 | # percentage | 32 | # percentage |
| 27 | - ratio = 100.0 / number_of_filters | 33 | + ratio = (100.0 / number_of_filters) |
| 28 | 34 | ||
| 29 | def UpdateProgress(obj, label=""): | 35 | def UpdateProgress(obj, label=""): |
| 30 | """ | 36 | """ |
| @@ -46,8 +52,16 @@ def ShowProgress(number_of_filters = 1): | @@ -46,8 +52,16 @@ def ShowProgress(number_of_filters = 1): | ||
| 46 | progress[0] = progress[0] + ratio*difference | 52 | progress[0] = progress[0] + ratio*difference |
| 47 | 53 | ||
| 48 | # Tell GUI to update progress status value | 54 | # Tell GUI to update progress status value |
| 49 | - ps.Publisher().sendMessage('Update status in GUI', | ||
| 50 | - (progress[0], label)) | 55 | + if (dialog_type == "GaugeProgress"): |
| 56 | + ps.Publisher().sendMessage('Update status in GUI', | ||
| 57 | + (progress[0], label)) | ||
| 58 | + else: | ||
| 59 | + if (int(progress[0]) == 99): | ||
| 60 | + progress[0] = 100 | ||
| 61 | + | ||
| 62 | + if not(dlg.Update(progress[0],label)): | ||
| 63 | + dlg.Close() | ||
| 64 | + | ||
| 51 | return progress[0] | 65 | return progress[0] |
| 52 | 66 | ||
| 53 | return UpdateProgress | 67 | return UpdateProgress |
invesalius/gui/dialogs.py
| @@ -78,19 +78,18 @@ class ProgressDialog(object): | @@ -78,19 +78,18 @@ class ProgressDialog(object): | ||
| 78 | ) | 78 | ) |
| 79 | 79 | ||
| 80 | self.dlg.Bind(wx.EVT_BUTTON, self.Cancel) | 80 | self.dlg.Bind(wx.EVT_BUTTON, self.Cancel) |
| 81 | - self.dlg.SetSize(wx.Size(200,150)) | 81 | + self.dlg.SetSize(wx.Size(215,150)) |
| 82 | 82 | ||
| 83 | def Cancel(self, evt): | 83 | def Cancel(self, evt): |
| 84 | ps.Publisher().sendMessage("Cancel DICOM load") | 84 | ps.Publisher().sendMessage("Cancel DICOM load") |
| 85 | 85 | ||
| 86 | - def Update(self, value): | ||
| 87 | - message = "Loading file %d of %d"%(value,self.maximum) | ||
| 88 | - if(value != self.maximum): | 86 | + def Update(self, value, message): |
| 87 | + if(int(value) != self.maximum): | ||
| 89 | self.dlg.Update(value,message) | 88 | self.dlg.Update(value,message) |
| 90 | return True | 89 | return True |
| 91 | else: | 90 | else: |
| 92 | return False | 91 | return False |
| 93 | - | 92 | + |
| 94 | def Close(self): | 93 | def Close(self): |
| 95 | self.dlg.Destroy() | 94 | self.dlg.Destroy() |
| 96 | 95 |
invesalius/gui/frame.py
| @@ -308,6 +308,10 @@ class StatusBar(wx.StatusBar): | @@ -308,6 +308,10 @@ class StatusBar(wx.StatusBar): | ||
| 308 | value, label = pubsub_evt.data | 308 | value, label = pubsub_evt.data |
| 309 | self.progress_bar.UpdateValue(value) | 309 | self.progress_bar.UpdateValue(value) |
| 310 | self.SetStatusText(label, 0) | 310 | self.SetStatusText(label, 0) |
| 311 | + if (int(value) >= 99): | ||
| 312 | + self.SetStatusText("",0) | ||
| 313 | + wx.Yield() | ||
| 314 | + | ||
| 311 | 315 | ||
| 312 | def UpdateStatusLabel(self, pubsub_evt): | 316 | def UpdateStatusLabel(self, pubsub_evt): |
| 313 | label = pubsub_evt.data | 317 | label = pubsub_evt.data |