Commit e63af012f1c31649c59778351f80ce3e2917b762

Authored by Paulo Henrique Junqueira Amorim
1 parent c899bff4

ENH: Improved progress bar

invesalius/data/surface.py
@@ -377,7 +377,7 @@ class SurfaceManager(): @@ -377,7 +377,7 @@ class SurfaceManager():
377 """ 377 """
378 matrix, filename_img, mask, spacing = pubsub_evt.data 378 matrix, filename_img, mask, spacing = pubsub_evt.data
379 min_value, max_value = mask.threshold_range 379 min_value, max_value = mask.threshold_range
380 - fill_holes = True 380 + fill_holes = False
381 381
382 #if len(surface_data) == 5: 382 #if len(surface_data) == 5:
383 #imagedata, colour, [min_value, max_value], \ 383 #imagedata, colour, [min_value, max_value], \
@@ -394,7 +394,7 @@ class SurfaceManager(): @@ -394,7 +394,7 @@ class SurfaceManager():
394 394
395 mode = 'CONTOUR' # 'GRAYSCALE' 395 mode = 'CONTOUR' # 'GRAYSCALE'
396 quality=_('Optimal *') 396 quality=_('Optimal *')
397 - keep_largest = True 397 + keep_largest = False
398 surface_name = "" 398 surface_name = ""
399 colour = mask.colour 399 colour = mask.colour
400 400
@@ -415,19 +415,19 @@ class SurfaceManager(): @@ -415,19 +415,19 @@ class SurfaceManager():
415 #if imagedata_resolution: 415 #if imagedata_resolution:
416 #imagedata = iu.ResampleImage3D(imagedata, imagedata_resolution) 416 #imagedata = iu.ResampleImage3D(imagedata, imagedata_resolution)
417 417
418 - #pipeline_size = 4  
419 - #if decimate_reduction:  
420 - #pipeline_size += 1  
421 - #if (smooth_iterations and smooth_relaxation_factor):  
422 - #pipeline_size += 1 418 + pipeline_size = 4
  419 + if decimate_reduction:
  420 + pipeline_size += 1
  421 + if (smooth_iterations and smooth_relaxation_factor):
  422 + pipeline_size += 1
423 #if fill_holes: 423 #if fill_holes:
424 - #pipeline_size += 1 424 + # pipeline_size += 1
425 #if keep_largest: 425 #if keep_largest:
426 - #pipeline_size += 1  
427 - 426 + # pipeline_size += 1
  427 +
428 ## Update progress value in GUI 428 ## Update progress value in GUI
429 - #UpdateProgress = vu.ShowProgress(pipeline_size)  
430 - #UpdateProgress(0, _("Generating 3D surface...")) 429 + UpdateProgress = vu.ShowProgress(pipeline_size)
  430 + UpdateProgress(0, _("Generating 3D surface..."))
431 431
432 #filename_img = tempfile.mktemp() 432 #filename_img = tempfile.mktemp()
433 433
@@ -452,7 +452,6 @@ class SurfaceManager(): @@ -452,7 +452,6 @@ class SurfaceManager():
452 piece_size = 20 452 piece_size = 20
453 453
454 n_pieces = int(round(matrix.shape[0] / piece_size + 0.5, 0)) 454 n_pieces = int(round(matrix.shape[0] / piece_size + 0.5, 0))
455 - print "n_pieces", n_pieces, matrix.shape  
456 455
457 q_in = multiprocessing.Queue() 456 q_in = multiprocessing.Queue()
458 q_out = multiprocessing.Queue() 457 q_out = multiprocessing.Queue()
@@ -463,8 +462,7 @@ class SurfaceManager(): @@ -463,8 +462,7 @@ class SurfaceManager():
463 matrix.shape, matrix.dtype, spacing, 462 matrix.shape, matrix.dtype, spacing,
464 mode, min_value, max_value, 463 mode, min_value, max_value,
465 decimate_reduction, smooth_relaxation_factor, 464 decimate_reduction, smooth_relaxation_factor,
466 - smooth_iterations, language, fill_holes, keep_largest,  
467 - flip_image, q_in, q_out) 465 + smooth_iterations, language, flip_image, q_in, q_out)
468 p.append(sp) 466 p.append(sp)
469 sp.start() 467 sp.start()
470 468
@@ -478,6 +476,18 @@ class SurfaceManager(): @@ -478,6 +476,18 @@ class SurfaceManager():
478 for i in p: 476 for i in p:
479 q_in.put(None) 477 q_in.put(None)
480 478
  479 + none_count = 1
  480 + while 1:
  481 + msg = pipe_out.recv()
  482 + if(msg is None):
  483 + none_count += 1
  484 + else:
  485 + UpdateProgress(msg[0]/(n_pieces * pipeline_size), msg[1])
  486 +
  487 + if none_count > n_pieces:
  488 + break
  489 +
  490 +
481 polydata_append = vtk.vtkAppendPolyData() 491 polydata_append = vtk.vtkAppendPolyData()
482 t = n_pieces 492 t = n_pieces
483 while t: 493 while t:
@@ -490,13 +500,18 @@ class SurfaceManager(): @@ -490,13 +500,18 @@ class SurfaceManager():
490 500
491 t -= 1 501 t -= 1
492 polydata = polydata_append.GetOutput() 502 polydata = polydata_append.GetOutput()
493 -  
494 clean = vtk.vtkCleanPolyData() 503 clean = vtk.vtkCleanPolyData()
  504 + clean.AddObserver("ProgressEvent", lambda obj,evt:
  505 + UpdateProgress(obj, _("Generating 3D surface...")))
495 clean.SetInput(polydata) 506 clean.SetInput(polydata)
496 clean.PointMergingOn() 507 clean.PointMergingOn()
  508 + clean.Update()
497 polydata = clean.GetOutput() 509 polydata = clean.GetOutput()
498 510
  511 +
499 smoother = vtk.vtkWindowedSincPolyDataFilter() 512 smoother = vtk.vtkWindowedSincPolyDataFilter()
  513 + smoother.AddObserver("ProgressEvent", lambda obj,evt:
  514 + UpdateProgress(obj, _("Generating 3D surface...")))
500 smoother.SetInput(polydata) 515 smoother.SetInput(polydata)
501 smoother.SetNumberOfIterations(smooth_iterations) 516 smoother.SetNumberOfIterations(smooth_iterations)
502 smoother.SetFeatureAngle(120) 517 smoother.SetFeatureAngle(120)
@@ -508,29 +523,48 @@ class SurfaceManager(): @@ -508,29 +523,48 @@ class SurfaceManager():
508 smoother.Update() 523 smoother.Update()
509 polydata = smoother.GetOutput() 524 polydata = smoother.GetOutput()
510 525
  526 + if keep_largest:
  527 + conn = vtk.vtkPolyDataConnectivityFilter()
  528 + conn.SetInput(polydata)
  529 + conn.SetExtractionModeToLargestRegion()
  530 + conn.AddObserver("ProgressEvent", lambda obj,evt:
  531 + UpdateProgress(obj, _("Generating 3D surface...")))
  532 + polydata = conn.GetOutput()
  533 +
  534 +
  535 + # Filter used to detect and fill holes. Only fill boundary edges holes.
  536 + #TODO: Hey! This piece of code is the same from
  537 + # polydata_utils.FillSurfaceHole, we need to review this.
  538 + if fill_holes:
  539 + filled_polydata = vtk.vtkFillHolesFilter()
  540 + filled_polydata.SetInput(polydata)
  541 + filled_polydata.SetHoleSize(300)
  542 + #filled_polydata.AddObserver("ProgressEvent", lambda obj,evt:
  543 + # UpdateProgress(obj, _("Generating 3D surface...")))
  544 + polydata = filled_polydata.GetOutput()
511 545
512 normals = vtk.vtkPolyDataNormals() 546 normals = vtk.vtkPolyDataNormals()
  547 + normals.AddObserver("ProgressEvent", lambda obj,evt:
  548 + UpdateProgress(obj, _("Generating 3D surface...")))
513 normals.SetInput(polydata) 549 normals.SetInput(polydata)
514 normals.SetFeatureAngle(80) 550 normals.SetFeatureAngle(80)
515 normals.AutoOrientNormalsOn() 551 normals.AutoOrientNormalsOn()
  552 + normals.Update()
516 polydata = normals.GetOutput() 553 polydata = normals.GetOutput()
517 - #decimation = vtk.vtkDecimatePro()  
518 - #decimation.SetInput(polydata)  
519 - #decimation.SetTargetReduction(0.3)  
520 - #decimation.PreserveTopologyOn()  
521 - #decimation.SplittingOff()  
522 - #decimation.BoundaryVertexDeletionOff()  
523 - #polydata = decimation.GetOutput()  
524 554
525 # Improve performance 555 # Improve performance
526 stripper = vtk.vtkStripper() 556 stripper = vtk.vtkStripper()
  557 + stripper.AddObserver("ProgressEvent", lambda obj,evt:
  558 + UpdateProgress(obj, _("Generating 3D surface...")))
527 stripper.SetInput(polydata) 559 stripper.SetInput(polydata)
528 stripper.PassThroughCellIdsOn() 560 stripper.PassThroughCellIdsOn()
529 stripper.PassThroughPointIdsOn() 561 stripper.PassThroughPointIdsOn()
  562 + stripper.Update()
  563 + polydata = stripper.GetOutput()
530 564
531 # Map polygonal data (vtkPolyData) to graphics primitives. 565 # Map polygonal data (vtkPolyData) to graphics primitives.
532 mapper = vtk.vtkPolyDataMapper() 566 mapper = vtk.vtkPolyDataMapper()
533 - mapper.SetInput(stripper.GetOutput()) 567 + mapper.SetInput(polydata)
534 mapper.ScalarVisibilityOff() 568 mapper.ScalarVisibilityOff()
535 mapper.ImmediateModeRenderingOn() # improve performance 569 mapper.ImmediateModeRenderingOn() # improve performance
536 570
@@ -601,15 +635,16 @@ class SurfaceManager(): @@ -601,15 +635,16 @@ class SurfaceManager():
601 # Save actor for future management tasks 635 # Save actor for future management tasks
602 self.actors_dict[surface.index] = actor 636 self.actors_dict[surface.index] = actor
603 637
604 -  
605 - ps.Publisher().sendMessage('Update status text in GUI',  
606 - _("Ready"))  
607 -  
608 ps.Publisher().sendMessage('Update surface info in GUI', 638 ps.Publisher().sendMessage('Update surface info in GUI',
609 (surface.index, surface.name, 639 (surface.index, surface.name,
610 surface.colour, surface.volume, 640 surface.colour, surface.volume,
611 surface.transparency)) 641 surface.transparency))
612 642
  643 + UpdateProgress(0, _("Ready"))
  644 + UpdateProgress(0, _("Ready"))
  645 + ps.Publisher().sendMessage('Update status text in GUI',
  646 + _("Ready"))
  647 +
613 ps.Publisher().sendMessage('End busy cursor') 648 ps.Publisher().sendMessage('End busy cursor')
614 649
615 650
invesalius/data/surface_process.py
@@ -13,8 +13,7 @@ class SurfaceProcess(multiprocessing.Process): @@ -13,8 +13,7 @@ class SurfaceProcess(multiprocessing.Process):
13 13
14 def __init__(self, pipe, filename, shape, dtype, spacing, mode, min_value, max_value, 14 def __init__(self, pipe, filename, shape, dtype, spacing, mode, min_value, max_value,
15 decimate_reduction, smooth_relaxation_factor, 15 decimate_reduction, smooth_relaxation_factor,
16 - smooth_iterations, language, fill_holes, keep_largest,  
17 - flip_image, q_in, q_out): 16 + smooth_iterations, language, flip_image, q_in, q_out):
18 17
19 multiprocessing.Process.__init__(self) 18 multiprocessing.Process.__init__(self)
20 self.pipe = pipe 19 self.pipe = pipe
@@ -27,8 +26,6 @@ class SurfaceProcess(multiprocessing.Process): @@ -27,8 +26,6 @@ class SurfaceProcess(multiprocessing.Process):
27 self.smooth_relaxation_factor = smooth_relaxation_factor 26 self.smooth_relaxation_factor = smooth_relaxation_factor
28 self.smooth_iterations = smooth_iterations 27 self.smooth_iterations = smooth_iterations
29 self.language = language 28 self.language = language
30 - self.fill_holes = fill_holes  
31 - self.keep_largest = keep_largest  
32 self.flip_image = flip_image 29 self.flip_image = flip_image
33 self.q_in = q_in 30 self.q_in = q_in
34 self.q_out = q_out 31 self.q_out = q_out
@@ -40,7 +37,6 @@ class SurfaceProcess(multiprocessing.Process): @@ -40,7 +37,6 @@ class SurfaceProcess(multiprocessing.Process):
40 shape=self.shape) 37 shape=self.shape)
41 while 1: 38 while 1:
42 roi = self.q_in.get() 39 roi = self.q_in.get()
43 - print roi  
44 if roi is None: 40 if roi is None:
45 break 41 break
46 self.CreateSurface(roi) 42 self.CreateSurface(roi)
@@ -60,77 +56,52 @@ class SurfaceProcess(multiprocessing.Process): @@ -60,77 +56,52 @@ class SurfaceProcess(multiprocessing.Process):
60 flip.Update() 56 flip.Update()
61 # Create vtkPolyData from vtkImageData 57 # Create vtkPolyData from vtkImageData
62 #print "Generating Polydata" 58 #print "Generating Polydata"
63 - #if self.mode == "CONTOUR": 59 + if self.mode == "CONTOUR":
64 #print "Contour" 60 #print "Contour"
65 - #contour = vtk.vtkContourFilter()  
66 - #contour.SetInput(image)  
67 - #contour.SetValue(0, self.min_value) # initial threshold  
68 - #contour.SetValue(1, self.max_value) # final threshold  
69 - #contour.ComputeScalarsOn()  
70 - #contour.ComputeGradientsOn()  
71 - #contour.ComputeNormalsOn()  
72 - #polydata = contour.GetOutput()  
73 - #else: #mode == "GRAYSCALE":  
74 - mcubes = vtk.vtkMarchingCubes()  
75 - mcubes.SetInput(flip.GetOutput())  
76 - mcubes.SetValue(0, self.min_value)  
77 - mcubes.SetValue(1, self.max_value)  
78 - mcubes.ComputeScalarsOff()  
79 - mcubes.ComputeGradientsOff()  
80 - mcubes.ComputeNormalsOff()  
81 - polydata = mcubes.GetOutput() 61 + contour = vtk.vtkContourFilter()
  62 + contour.SetInput(flip.GetOutput())
  63 + contour.SetValue(0, self.min_value) # initial threshold
  64 + contour.SetValue(1, self.max_value) # final threshold
  65 + contour.ComputeScalarsOn()
  66 + contour.ComputeGradientsOn()
  67 + contour.ComputeNormalsOn()
  68 + contour.AddObserver("ProgressEvent", lambda obj,evt:
  69 + self.SendProgress(obj, _("Generating 3D surface...")))
  70 + polydata = contour.GetOutput()
  71 + else: #mode == "GRAYSCALE":
  72 + mcubes = vtk.vtkMarchingCubes()
  73 + mcubes.SetInput(flip.GetOutput())
  74 + mcubes.SetValue(0, self.min_value)
  75 + mcubes.SetValue(1, self.max_value)
  76 + mcubes.ComputeScalarsOff()
  77 + mcubes.ComputeGradientsOff()
  78 + mcubes.ComputeNormalsOff()
  79 + mcubes.AddObserver("ProgressEvent", lambda obj,evt:
  80 + self.SendProgress(obj, _("Generating 3D surface...")))
  81 + polydata = mcubes.GetOutput()
82 82
83 triangle = vtk.vtkTriangleFilter() 83 triangle = vtk.vtkTriangleFilter()
84 triangle.SetInput(polydata) 84 triangle.SetInput(polydata)
  85 + triangle.AddObserver("ProgressEvent", lambda obj,evt:
  86 + self.SendProgress(obj, _("Generating 3D surface...")))
85 triangle.Update() 87 triangle.Update()
86 polydata = triangle.GetOutput() 88 polydata = triangle.GetOutput()
87 89
88 - bounds = polydata.GetBounds()  
89 - origin = ((bounds[1] + bounds[0]) / 2.0, (bounds[3] + bounds[2])/2.0,  
90 - (bounds[5] + bounds[4]) / 2.0)  
91 -  
92 - print "Bounds is", bounds  
93 - print "origin is", origin  
94 -  
95 - #print "Decimating"  
96 - decimation = vtk.vtkDecimatePro()  
97 - decimation.SetInput(polydata)  
98 - decimation.SetTargetReduction(0.3)  
99 - #decimation.PreserveTopologyOn()  
100 - decimation.SplittingOff()  
101 - decimation.BoundaryVertexDeletionOff()  
102 - polydata = decimation.GetOutput()  
103 -  
104 - #decimation = vtk.vtkQuadricClustering()  
105 - #decimation.SetInput(polydata)  
106 - #decimation.AutoAdjustNumberOfDivisionsOff()  
107 - #decimation.SetDivisionOrigin(0, 0, 0)  
108 - #decimation.SetDivisionSpacing(self.spacing)  
109 - #decimation.SetFeaturePointsAngle(80)  
110 - #decimation.UseFeaturePointsOn()  
111 - #decimation.UseFeatureEdgesOn()  
112 - #ecimation.CopyCellDataOn() 90 + if self.decimate_reduction:
  91 +
  92 + #print "Decimating"
  93 + decimation = vtk.vtkDecimatePro()
  94 + decimation.SetInput(polydata)
  95 + decimation.SetTargetReduction(0.3)
  96 + decimation.AddObserver("ProgressEvent", lambda obj,evt:
  97 + self.SendProgress(obj, _("Generating 3D surface...")))
  98 + #decimation.PreserveTopologyOn()
  99 + decimation.SplittingOff()
  100 + decimation.BoundaryVertexDeletionOff()
  101 + polydata = decimation.GetOutput()
  102 +
  103 + self.pipe.send(None)
113 104
114 - #print "Division", decimation.GetNumberOfDivisions()  
115 -  
116 - #polydata = decimation.GetOutput()  
117 -  
118 - #if self.smooth_iterations and self.smooth_relaxation_factor:  
119 - #print "Smoothing"  
120 - #smoother = vtk.vtkWindowedSincPolyDataFilter()  
121 - #smoother.SetInput(polydata)  
122 - #smoother.SetNumberOfIterations(self.smooth_iterations)  
123 - #smoother.SetFeatureAngle(120)  
124 - #smoother.SetNumberOfIterations(30)  
125 - #smoother.BoundarySmoothingOn()  
126 - #smoother.SetPassBand(0.01)  
127 - #smoother.FeatureEdgeSmoothingOn()  
128 - #smoother.NonManifoldSmoothingOn()  
129 - #smoother.NormalizeCoordinatesOn()  
130 - #smoother.Update()  
131 - #polydata = smoother.GetOutput()  
132 -  
133 - print "Saving"  
134 filename = tempfile.mktemp(suffix='_%s.vtp' % (self.pid)) 105 filename = tempfile.mktemp(suffix='_%s.vtp' % (self.pid))
135 writer = vtk.vtkXMLPolyDataWriter() 106 writer = vtk.vtkXMLPolyDataWriter()
136 writer.SetInput(polydata) 107 writer.SetInput(polydata)
invesalius/data/vtk_utils.py
@@ -74,7 +74,6 @@ def ShowProgress(number_of_filters = 1, @@ -74,7 +74,6 @@ def ShowProgress(number_of_filters = 1,
74 74
75 # final progress status value 75 # final progress status value
76 progress[0] = progress[0] + ratio*difference 76 progress[0] = progress[0] + ratio*difference
77 -  
78 # Tell GUI to update progress status value 77 # Tell GUI to update progress status value
79 if (dialog_type == "GaugeProgress"): 78 if (dialog_type == "GaugeProgress"):
80 ps.Publisher().sendMessage('Update status in GUI', 79 ps.Publisher().sendMessage('Update status in GUI',