| 
					
				 | 
			
			
				@@ -1,5 +1,6 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #!/usr/bin/env python3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import argparse 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import contextlib 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from collections import defaultdict, namedtuple 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from datetime import datetime, timedelta 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from importlib import import_module 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -16,12 +17,8 @@ import threading 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import time 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import warnings 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import tqdm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    from clint.textui import progress 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-except ImportError: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    print("Warning: clint is not installed, no fancy progressbars in the terminal for you.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    progress = None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import numpy 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import yaml 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -476,7 +473,7 @@ def print_survival_function(kmf, sampling): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         pass 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-def interpolate_burndown_matrix(matrix, granularity, sampling): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def interpolate_burndown_matrix(matrix, granularity, sampling, progress=False): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     daily = numpy.zeros( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         (matrix.shape[0] * granularity, matrix.shape[1] * sampling), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         dtype=numpy.float32) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -488,7 +485,7 @@ def interpolate_burndown_matrix(matrix, granularity, sampling): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ⌄ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     bands, y 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for y in range(matrix.shape[0]): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for y in tqdm.tqdm(range(matrix.shape[0]), disable=(not progress)): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         for x in range(matrix.shape[1]): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if y * granularity > (x + 1) * sampling: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 # the future is zeros 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -614,7 +611,14 @@ def floor_datetime(dt, duration): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return datetime.fromtimestamp(dt.timestamp() - dt.timestamp() % duration) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-def load_burndown(header, name, matrix, resample, report_survival=True): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def load_burndown( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    header, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    name, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    matrix, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    resample, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    report_survival=True, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    interpolation_progress=False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     pandas = import_pandas() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     start, last, sampling, granularity, tick = header 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -632,7 +636,12 @@ def load_burndown(header, name, matrix, resample, report_survival=True): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         # Interpolate the day x day matrix. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         # Each day brings equal weight in the granularity. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         # Sampling's interpolation is linear. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        daily = interpolate_burndown_matrix(matrix, granularity, sampling) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        daily = interpolate_burndown_matrix( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            matrix=matrix, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            granularity=granularity, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            sampling=sampling, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            progress=interpolation_progress, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         daily[(last - start).days:] = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         # Resample the bands 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         aliases = { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -915,14 +924,10 @@ def plot_burndown(args, target, name, matrix, date_range_sampling, labels, granu 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 def plot_many_burndown(args, target, header, parts): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if not args.output: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         print("Warning: output not set, showing %d plots." % len(parts)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    itercnt = progress.bar(parts, expected_size=len(parts)) \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if progress is not None else parts 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     stdout = io.StringIO() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for name, matrix in itercnt: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        backup = sys.stdout 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        sys.stdout = stdout 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        plot_burndown(args, target, *load_burndown(header, name, matrix, args.resample)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        sys.stdout = backup 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for name, matrix in tqdm.tqdm(parts): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        with contextlib.redirect_stdout(stdout): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            plot_burndown(args, target, *load_burndown(header, name, matrix, args.resample)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     sys.stdout.write(stdout.getvalue()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1441,18 +1446,21 @@ def order_commits(chosen_people, days, people): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         series[i] = arr.transpose() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     # calculate the distance matrix using dynamic time warping 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     dists = numpy.full((len(series),) * 2, -100500, dtype=numpy.float32) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for x, serx in enumerate(series): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        dists[x, x] = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for y, sery in enumerate(series[x + 1:], start=x + 1): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            min_day = int(min(serx[0][0], sery[0][0])) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            max_day = int(max(serx[-1][0], sery[-1][0])) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            arrx = numpy.zeros(max_day - min_day + 1, dtype=numpy.float32) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            arry = numpy.zeros_like(arrx) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            arrx[serx[:, 0].astype(int) - min_day] = serx[:, 1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            arry[sery[:, 0].astype(int) - min_day] = sery[:, 1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            # L1 norm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dist, _ = fastdtw(arrx, arry, radius=5, dist=1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dists[x, y] = dists[y, x] = dist 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # TODO: what's the total for this progress bar? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    with tqdm.tqdm() as pb: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for x, serx in enumerate(series): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            dists[x, x] = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for y, sery in enumerate(series[x + 1:], start=x + 1): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                min_day = int(min(serx[0][0], sery[0][0])) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                max_day = int(max(serx[-1][0], sery[-1][0])) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                arrx = numpy.zeros(max_day - min_day + 1, dtype=numpy.float32) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                arry = numpy.zeros_like(arrx) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                arrx[serx[:, 0].astype(int) - min_day] = serx[:, 1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                arry[sery[:, 0].astype(int) - min_day] = sery[:, 1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                # L1 norm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                dist, _ = fastdtw(arrx, arry, radius=5, dist=1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                dists[x, y] = dists[y, x] = dist 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                pb.update() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     print("Ordering the series") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     route = seriate(dists) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return dists, devseries, devstats, route 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1794,7 +1802,7 @@ def main(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         plot_burndown(args, "project", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                       *load_burndown(full_header, *reader.get_project_burndown(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                     resample=args.resample)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                     resample=args.resample, interpolation_progress=True)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     def files_burndown(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         try: 
			 |