[Bf-extensions-cvs] [e25bc52] master: Generic progress report system with optional stdout and wm.progress output.

Lukas Tönne noreply at git.blender.org
Mon Dec 15 14:31:36 CET 2014


Commit: e25bc52dbebc5a189b6f253c634fd97042713d69
Author: Lukas Tönne
Date:   Mon Dec 15 14:28:17 2014 +0100
Branches: master
https://developer.blender.org/rBACe25bc52dbebc5a189b6f253c634fd97042713d69

Generic progress report system with optional stdout and wm.progress
output.

This works as a context manager: For any step in the process a loop can
be wrapped in the ProgressContext context manager. These classes are
generated by make_progress_reporter, so the main output options can be
defined on a high level, while actual number of steps is defined only
when actually running the job and the total amount of items is known.

===================================================================

M	object_physics_meadow/hierarchical_dart_throw.py
M	object_physics_meadow/meadow.py
M	object_physics_meadow/patch.py
M	object_physics_meadow/ui.py
M	object_physics_meadow/util.py

===================================================================

diff --git a/object_physics_meadow/hierarchical_dart_throw.py b/object_physics_meadow/hierarchical_dart_throw.py
index 77b84f1..78f8ca7 100644
--- a/object_physics_meadow/hierarchical_dart_throw.py
+++ b/object_physics_meadow/hierarchical_dart_throw.py
@@ -51,6 +51,10 @@ class GridLevel():
         self.cells.append(cell)
         return cell
 
+    @staticmethod
+    def num_cells_in_range(imin, imax, jmin, jmax, kmin, kmax):
+        return (imax - imin) * (jmax - jmin) * (kmax - kmin)
+
     def set_active_cells(self, imin, imax, jmin, jmax, kmin, kmax):
         tot = (imax - imin) * (jmax - jmin) * (kmax - kmin)
         self.cells = [None] * tot
@@ -58,6 +62,7 @@ class GridLevel():
         for k in range(kmin, kmax):
             for j in range(jmin, jmax):
                 for i in range(imin, imax):
+                    progress_add(1)
                     self.cells[c] = GridCell(i, j, k)
                     c += 1
 
@@ -119,7 +124,17 @@ class PointCell():
         self.points = []
 
 class PointGrid():
-    def __init__(self, radius, b0, gridmin, gridmax):
+    @staticmethod
+    def num_cells(radius, gridmin, gridmax):
+        size = radius
+        amin = ifloor(gridmin[0] / size) - 1
+        bmin = ifloor(gridmin[1] / size) - 1
+        na = ifloor(gridmax[0] / size) + 2 - amin
+        nb = ifloor(gridmax[1] / size) + 2 - bmin
+        
+        return na * nb
+
+    def __init__(self, radius, gridmin, gridmax):
         width = gridmax[0] - gridmin[0]
         height = gridmax[1] - gridmin[1]
         size = radius
@@ -132,8 +147,13 @@ class PointGrid():
         self.na = ifloor(gridmax[0] / size) + 2 - self.amin
         self.nb = ifloor(gridmax[1] / size) + 2 - self.bmin
         
+        # modified range generator for progress reports
+        def range_progress(tot):
+            for i in range(tot):
+                progress_add(1)
+                yield i
         # note: row-major, so we can address it with cells[i][j]
-        self.cells = tuple(tuple(PointCell() for j in range(self.nb)) for i in range(self.na))
+        self.cells = tuple(tuple(PointCell() for j in range_progress(self.nb)) for i in range(self.na))
 
     def grid_from_loc(self, point):
         s = self.invsize
@@ -216,7 +236,8 @@ def split_cell(radius2, b0, pgrid, child_level, cell, x0, x1, y0, y1, z0, z1):
             if not is_covered(radius2, b0, pgrid, child_level, ci, cj, cx0, cx1, cy0, cy1):
                 child_cell = child_level.activate(ci, cj, ck)
 
-def hierarchical_dart_throw_gen(radius, max_levels, xmin, xmax, ymin, ymax):
+def hierarchical_dart_throw_gen(radius, max_levels, xmin, xmax, ymin, ymax,
+                                progress_reporter=DummyProgressContext):
     radius2 = radius * radius
     gridmin = (xmin, ymin)
     gridmax = (xmax, ymax)
@@ -232,28 +253,33 @@ def hierarchical_dart_throw_gen(radius, max_levels, xmin, xmax, ymin, ymax):
         levels = [base_level] + [GridLevel(i, base_level.size / (2**i), radius) for i in range(1, max_levels)]
         epsilon = levels[-1].weight * 0.5
         
-        base_level.set_active_cells(imin, imax, jmin, jmax, 0, 1)
+        with progress_reporter("Activate Cells", 0, GridLevel.num_cells_in_range(imin, imax, jmin, jmax, 0, 1)):
+            base_level.set_active_cells(imin, imax, jmin, jmax, 0, 1)
         
-        pgrid = PointGrid(radius, b0, gridmin, gridmax)
+        with progress_reporter("Init Spatial Grid", 0, PointGrid.num_cells(radius, gridmin, gridmax)):
+            pgrid = PointGrid(radius, gridmin, gridmax)
         
-        for i in range(num):
-            if not any(level.cells for level in levels):
-                break
-            
-            level, cell = pop_cell(levels)
-            if level:
-                x0, x1, y0, y1, z0, z1 = level.cell_corners(cell)
+        with progress_reporter("Generate Samples", 0, num):
+            for i in range(num):
+                progress_add(1)
                 
-                # test coverage
-                if not is_covered(radius2, b0, pgrid, level, cell.i, cell.j, x0, x1, y0, y1):
-                    point = level.sample(x0, x1, y0, y1, z0, z1)
-                    if test_disk(radius2, pgrid, point, level, cell.i, cell.j):
-                        yield point
-                        pgrid.insert(point)
-                    else:
-                        if level.index < max_levels - 1:
-                            split_cell(radius2, b0, pgrid, levels[level.index+1], cell, x0, x1, y0, y1, z0, z1)
-            else:
-                break
-    
+                if not any(level.cells for level in levels):
+                    break
+                
+                level, cell = pop_cell(levels)
+                if level:
+                    x0, x1, y0, y1, z0, z1 = level.cell_corners(cell)
+                    
+                    # test coverage
+                    if not is_covered(radius2, b0, pgrid, level, cell.i, cell.j, x0, x1, y0, y1):
+                        point = level.sample(x0, x1, y0, y1, z0, z1)
+                        if test_disk(radius2, pgrid, point, level, cell.i, cell.j):
+                            yield point
+                            pgrid.insert(point)
+                        else:
+                            if level.index < max_levels - 1:
+                                split_cell(radius2, b0, pgrid, levels[level.index+1], cell, x0, x1, y0, y1, z0, z1)
+                else:
+                    break
+
     return gen
diff --git a/object_physics_meadow/meadow.py b/object_physics_meadow/meadow.py
index e5013d7..6642ea9 100644
--- a/object_physics_meadow/meadow.py
+++ b/object_physics_meadow/meadow.py
@@ -26,6 +26,7 @@ from object_physics_meadow import patch, blob
 from object_physics_meadow.duplimesh import project_on_ground
 #from object_physics_meadow import dupliparticle
 #from object_physics_meadow.pointcache import cache_filename
+from object_physics_meadow.util import *
 
 from object_physics_meadow.best_candidate import best_candidate_gen
 from object_physics_meadow.hierarchical_dart_throw import hierarchical_dart_throw_gen
@@ -44,7 +45,7 @@ def make_samples(context, gridob, groundob):
     
     # get a sample generator implementation
     #gen = best_candidate_gen(groundob.meadow.patch_radius, xmin, xmax, ymin, ymax)
-    gen = hierarchical_dart_throw_gen(groundob.meadow.patch_radius, groundob.meadow.sampling_levels, xmin, xmax, ymin, ymax)
+    gen = hierarchical_dart_throw_gen(groundob.meadow.patch_radius, groundob.meadow.sampling_levels, xmin, xmax, ymin, ymax, progress_reporter=make_progress_reporter(True, True))
     
     mat = groundob.matrix_world
     loc2D = [(mat * Vector(p[0:3] + (1.0,)))[0:2] for p in gen(groundob.meadow.seed, groundob.meadow.max_patches)]
@@ -59,17 +60,17 @@ def make_blobs(context, gridob, groundob):
     if use_profiling:
         prof = cProfile.Profile()
         prof.enable()
-        samples2D = make_samples(context, gridob, groundob)
-        blob.make_blobs(context, gridob, groundob, samples2D, groundob.meadow.patch_radius)
+    
+    samples2D = make_samples(context, gridob, groundob)
+    blob.make_blobs(context, gridob, groundob, samples2D, groundob.meadow.patch_radius)
+
+    if use_profiling:
         prof.disable()
 
         s = io.StringIO()
         ps = pstats.Stats(prof, stream=s).sort_stats('tottime')
         ps.print_stats()
         print(s.getvalue())
-    else:
-        samples2D = make_samples(context, gridob, groundob)
-        blob.make_blobs(context, gridob, groundob, samples2D, groundob.meadow.patch_radius)
 
 ### Patch copies for simulation ###
 def make_patches(context, gridob, groundob):
diff --git a/object_physics_meadow/patch.py b/object_physics_meadow/patch.py
index eae3b71..888c70d 100644
--- a/object_physics_meadow/patch.py
+++ b/object_physics_meadow/patch.py
@@ -236,52 +236,53 @@ def bake_psys(context, ob, psys):
     # restore
     ob.particle_systems.active = curpsys
 
-def bake_all(context):
+def count_bakeable(context):
+    num = 0
+    for ob in patch_objects(context):
+        for psys in ob.particle_systems:
+            num += 1
+    return num
+
+def bake_all(context, progress_reporter):
     settings = _settings.get(context)
     wm = context.window_manager
     
     total_time = 0.0
     avg_time = 0.0
     
-    # XXX Note: wm.progress updates are disabled for now, because the bake
-    # operator overrides this with it's own progress numbers ...
-    
     total = count_bakeable(context)
-    #wm.progress_begin(0, total)
-    
-    num = 0
-    for ob in patch_objects(context):
-        for psys in ob.particle_systems:
-            sys.stdout.write("Baking blob {}/{} ... ".format(str(num).rjust(5), str(total).ljust(5)))
-            sys.stdout.flush()
-            
-            start_time = time.time()
-            
-            bake_psys(context, ob, psys)
-            
-            duration = time.time() - start_time
-            total_time += duration
-            avg_time = total_time / float(num + 1)
-            
-            #wm.progress_update(num)
-            time_string = lambda x: time.strftime("%H:%M:%S", time.gmtime(x)) + ".%02d" % (int(x * 100.0) % 100)
-            durstr = time_string(duration)
-            avgstr = time_string(avg_time) if avg_time > 0.0 else "--:--:--"
-            etastr = time_string(avg_time * (total - num)) if avg_time > 0.0 else "--:--:--"
-            sys.stdout.write("{} (avg. {}, ETA {})\n".format(durstr, avgstr, etastr))
-            sys.stdout.flush()
-            num += 1
     
-    #wm.progress_end()
-
-def count_bakeable(context):
-    num = 0
-    for ob in patch_objects(context):
-        for psys in ob.particle_systems:
-            num += 1
-    return num
+    with progress_reporter("Bake Blob", 0, total):
+        """
+        num = 0
+        """
+        for ob in patch_objects(context):
+            for psys in ob.particle_systems:
+                """
+                sys.stdout.write("Baking blob {}/{} ... ".format(str(num).rjust(5), str(total).ljust(5)))
+                sys.stdout.flush()
+                
+                start_time = time.time()
+                """
+                
+           

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list