Commit e63af012f1c31649c59778351f80ce3e2917b762
1 parent
c899bff4
Exists in
master
and in
5 other branches
ENH: Improved progress bar
Showing
3 changed files
with
102 additions
and
97 deletions
Show diff stats
invesalius/data/surface.py
... | ... | @@ -377,7 +377,7 @@ class SurfaceManager(): |
377 | 377 | """ |
378 | 378 | matrix, filename_img, mask, spacing = pubsub_evt.data |
379 | 379 | min_value, max_value = mask.threshold_range |
380 | - fill_holes = True | |
380 | + fill_holes = False | |
381 | 381 | |
382 | 382 | #if len(surface_data) == 5: |
383 | 383 | #imagedata, colour, [min_value, max_value], \ |
... | ... | @@ -394,7 +394,7 @@ class SurfaceManager(): |
394 | 394 | |
395 | 395 | mode = 'CONTOUR' # 'GRAYSCALE' |
396 | 396 | quality=_('Optimal *') |
397 | - keep_largest = True | |
397 | + keep_largest = False | |
398 | 398 | surface_name = "" |
399 | 399 | colour = mask.colour |
400 | 400 | |
... | ... | @@ -415,19 +415,19 @@ class SurfaceManager(): |
415 | 415 | #if imagedata_resolution: |
416 | 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 | 423 | #if fill_holes: |
424 | - #pipeline_size += 1 | |
424 | + # pipeline_size += 1 | |
425 | 425 | #if keep_largest: |
426 | - #pipeline_size += 1 | |
427 | - | |
426 | + # pipeline_size += 1 | |
427 | + | |
428 | 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 | 432 | #filename_img = tempfile.mktemp() |
433 | 433 | |
... | ... | @@ -452,7 +452,6 @@ class SurfaceManager(): |
452 | 452 | piece_size = 20 |
453 | 453 | |
454 | 454 | n_pieces = int(round(matrix.shape[0] / piece_size + 0.5, 0)) |
455 | - print "n_pieces", n_pieces, matrix.shape | |
456 | 455 | |
457 | 456 | q_in = multiprocessing.Queue() |
458 | 457 | q_out = multiprocessing.Queue() |
... | ... | @@ -463,8 +462,7 @@ class SurfaceManager(): |
463 | 462 | matrix.shape, matrix.dtype, spacing, |
464 | 463 | mode, min_value, max_value, |
465 | 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 | 466 | p.append(sp) |
469 | 467 | sp.start() |
470 | 468 | |
... | ... | @@ -478,6 +476,18 @@ class SurfaceManager(): |
478 | 476 | for i in p: |
479 | 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 | 491 | polydata_append = vtk.vtkAppendPolyData() |
482 | 492 | t = n_pieces |
483 | 493 | while t: |
... | ... | @@ -490,13 +500,18 @@ class SurfaceManager(): |
490 | 500 | |
491 | 501 | t -= 1 |
492 | 502 | polydata = polydata_append.GetOutput() |
493 | - | |
494 | 503 | clean = vtk.vtkCleanPolyData() |
504 | + clean.AddObserver("ProgressEvent", lambda obj,evt: | |
505 | + UpdateProgress(obj, _("Generating 3D surface..."))) | |
495 | 506 | clean.SetInput(polydata) |
496 | 507 | clean.PointMergingOn() |
508 | + clean.Update() | |
497 | 509 | polydata = clean.GetOutput() |
498 | 510 | |
511 | + | |
499 | 512 | smoother = vtk.vtkWindowedSincPolyDataFilter() |
513 | + smoother.AddObserver("ProgressEvent", lambda obj,evt: | |
514 | + UpdateProgress(obj, _("Generating 3D surface..."))) | |
500 | 515 | smoother.SetInput(polydata) |
501 | 516 | smoother.SetNumberOfIterations(smooth_iterations) |
502 | 517 | smoother.SetFeatureAngle(120) |
... | ... | @@ -508,29 +523,48 @@ class SurfaceManager(): |
508 | 523 | smoother.Update() |
509 | 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 | 546 | normals = vtk.vtkPolyDataNormals() |
547 | + normals.AddObserver("ProgressEvent", lambda obj,evt: | |
548 | + UpdateProgress(obj, _("Generating 3D surface..."))) | |
513 | 549 | normals.SetInput(polydata) |
514 | 550 | normals.SetFeatureAngle(80) |
515 | 551 | normals.AutoOrientNormalsOn() |
552 | + normals.Update() | |
516 | 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 | 555 | # Improve performance |
526 | 556 | stripper = vtk.vtkStripper() |
557 | + stripper.AddObserver("ProgressEvent", lambda obj,evt: | |
558 | + UpdateProgress(obj, _("Generating 3D surface..."))) | |
527 | 559 | stripper.SetInput(polydata) |
528 | 560 | stripper.PassThroughCellIdsOn() |
529 | 561 | stripper.PassThroughPointIdsOn() |
562 | + stripper.Update() | |
563 | + polydata = stripper.GetOutput() | |
530 | 564 | |
531 | 565 | # Map polygonal data (vtkPolyData) to graphics primitives. |
532 | 566 | mapper = vtk.vtkPolyDataMapper() |
533 | - mapper.SetInput(stripper.GetOutput()) | |
567 | + mapper.SetInput(polydata) | |
534 | 568 | mapper.ScalarVisibilityOff() |
535 | 569 | mapper.ImmediateModeRenderingOn() # improve performance |
536 | 570 | |
... | ... | @@ -601,15 +635,16 @@ class SurfaceManager(): |
601 | 635 | # Save actor for future management tasks |
602 | 636 | self.actors_dict[surface.index] = actor |
603 | 637 | |
604 | - | |
605 | - ps.Publisher().sendMessage('Update status text in GUI', | |
606 | - _("Ready")) | |
607 | - | |
608 | 638 | ps.Publisher().sendMessage('Update surface info in GUI', |
609 | 639 | (surface.index, surface.name, |
610 | 640 | surface.colour, surface.volume, |
611 | 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 | 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 | 13 | |
14 | 14 | def __init__(self, pipe, filename, shape, dtype, spacing, mode, min_value, max_value, |
15 | 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 | 18 | multiprocessing.Process.__init__(self) |
20 | 19 | self.pipe = pipe |
... | ... | @@ -27,8 +26,6 @@ class SurfaceProcess(multiprocessing.Process): |
27 | 26 | self.smooth_relaxation_factor = smooth_relaxation_factor |
28 | 27 | self.smooth_iterations = smooth_iterations |
29 | 28 | self.language = language |
30 | - self.fill_holes = fill_holes | |
31 | - self.keep_largest = keep_largest | |
32 | 29 | self.flip_image = flip_image |
33 | 30 | self.q_in = q_in |
34 | 31 | self.q_out = q_out |
... | ... | @@ -40,7 +37,6 @@ class SurfaceProcess(multiprocessing.Process): |
40 | 37 | shape=self.shape) |
41 | 38 | while 1: |
42 | 39 | roi = self.q_in.get() |
43 | - print roi | |
44 | 40 | if roi is None: |
45 | 41 | break |
46 | 42 | self.CreateSurface(roi) |
... | ... | @@ -60,77 +56,52 @@ class SurfaceProcess(multiprocessing.Process): |
60 | 56 | flip.Update() |
61 | 57 | # Create vtkPolyData from vtkImageData |
62 | 58 | #print "Generating Polydata" |
63 | - #if self.mode == "CONTOUR": | |
59 | + if self.mode == "CONTOUR": | |
64 | 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 | 83 | triangle = vtk.vtkTriangleFilter() |
84 | 84 | triangle.SetInput(polydata) |
85 | + triangle.AddObserver("ProgressEvent", lambda obj,evt: | |
86 | + self.SendProgress(obj, _("Generating 3D surface..."))) | |
85 | 87 | triangle.Update() |
86 | 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 | 105 | filename = tempfile.mktemp(suffix='_%s.vtp' % (self.pid)) |
135 | 106 | writer = vtk.vtkXMLPolyDataWriter() |
136 | 107 | writer.SetInput(polydata) | ... | ... |
invesalius/data/vtk_utils.py
... | ... | @@ -74,7 +74,6 @@ def ShowProgress(number_of_filters = 1, |
74 | 74 | |
75 | 75 | # final progress status value |
76 | 76 | progress[0] = progress[0] + ratio*difference |
77 | - | |
78 | 77 | # Tell GUI to update progress status value |
79 | 78 | if (dialog_type == "GaugeProgress"): |
80 | 79 | ps.Publisher().sendMessage('Update status in GUI', | ... | ... |