|
9 | 9 | import uuid
|
10 | 10 | try:
|
11 | 11 | from IPython.core.display import HTML, Javascript, display
|
12 |
| - |
13 |
| - have_ipython = True |
14 | 12 | except ImportError:
|
15 |
| - have_ipython = False |
| 13 | + pass |
16 | 14 |
|
17 |
| -class ProgressBar: |
18 |
| - def __init__(self, iterations): |
19 |
| - self.iterations = iterations |
20 |
| - self.prog_bar = '[]' |
21 |
| - self.fill_char = '*' |
22 |
| - self.width = 40 |
23 |
| - self.__update_amount(0) |
| 15 | +__all__ = ['progress_bar'] |
24 | 16 |
|
| 17 | +class ProgressBar(object): |
| 18 | + def __init__(self, iterations, animation_interval = .5): |
| 19 | + self.iterations = iterations |
25 | 20 | self.start = time.time()
|
26 | 21 | self.last = 0
|
27 |
| - if have_ipython: |
28 |
| - self.animate = self.animate_ipython |
29 |
| - self.divid = str(uuid.uuid4()) |
30 |
| - self.sec_id = str(uuid.uuid4()) |
31 |
| - |
32 |
| - pb = HTML( |
33 |
| - """ |
34 |
| - <div style="float: left; border: 1px solid black; width:500px"> |
35 |
| - <div id="%s" style="background-color:blue; width:0%%"> </div> |
36 |
| - </div> |
37 |
| - <label id="%s" style="padding-left: 10px;" text = ""/> |
38 |
| - """ % (self.divid,self.sec_id)) |
39 |
| - display(pb) |
40 |
| - else: |
41 |
| - self.animate = self.animate_noipython |
42 |
| - |
43 |
| - def animate_noipython(self, iter): |
44 |
| - if sys.platform.lower().startswith('win'): |
45 |
| - print(self, '\r', end='') |
46 |
| - else: |
47 |
| - print(self) |
48 |
| - self.update_iteration(iter) |
49 |
| - |
50 |
| - def animate_ipython(self, iter): |
51 |
| - elapsed = time.time() - self.start |
52 |
| - iter = iter + 1 |
53 |
| - if elapsed - self.last > .5 or iter == self.iterations: |
54 |
| - self.last = elapsed |
| 22 | + self.animation_interval = animation_interval |
55 | 23 |
|
56 |
| - self.update_iteration(iter) |
57 |
| - fraction = int(100*iter/float(self.iterations)) |
| 24 | + def percentage(self, i): |
| 25 | + return 100*i/float(self.iterations) |
58 | 26 |
|
59 |
| - display(Javascript("$('div#%s').width('%i%%')" % (self.divid, fraction))) |
60 |
| - display(Javascript("$('label#%s').text('%i%% in %.1f sec')" % (self.sec_id, fraction, round(elapsed, 1)))) |
| 27 | + def update(self, i): |
| 28 | + elapsed = time.time() - self.start |
| 29 | + i = i + 1 |
| 30 | + |
| 31 | + if elapsed - self.last > self.animation_interval or i == self.iterations: |
| 32 | + self.animate(i+1, elapsed) |
| 33 | + self.last = elapsed |
| 34 | + |
| 35 | +class TextProgressBar(ProgressBar): |
| 36 | + def __init__(self, iterations, printer): |
| 37 | + self.fill_char = '-' |
| 38 | + self.width = 40 |
| 39 | + self.printer = printer |
61 | 40 |
|
62 |
| - def update_iteration(self, elapsed_iter): |
63 |
| - self.__update_amount((elapsed_iter / float(self.iterations)) * 100.0) |
64 |
| - self.prog_bar += ' %d of %s complete' % (elapsed_iter, self.iterations) |
| 41 | + ProgressBar.__init__(self, iterations) |
| 42 | + self.update(0) |
65 | 43 |
|
| 44 | + def animate(self, i, elapsed): |
| 45 | + self.printer(self.progbar(i, elapsed)) |
66 | 46 |
|
67 |
| - def __update_amount(self, new_amount): |
68 |
| - percent_done = int(round((new_amount / 100.0) * 100.0)) |
| 47 | + |
| 48 | + def progbar(self,i, elapsed): |
| 49 | + bar = self.bar(self.percentage(i)) |
| 50 | + return "[%s] %i of %i complete in %.1f sec" % (bar, i, self.iterations, round(elapsed,1)) |
| 51 | + |
| 52 | + def bar(self, percent): |
69 | 53 | all_full = self.width - 2
|
70 |
| - num_hashes = int(round((percent_done / 100.0) * all_full)) |
71 |
| - self.prog_bar = '[' + self.fill_char * num_hashes + ' ' * (all_full - num_hashes) + ']' |
72 |
| - pct_place = (len(self.prog_bar) / 2) - len(str(percent_done)) |
73 |
| - pct_string = '%d%%' % percent_done |
74 |
| - self.prog_bar = self.prog_bar[0:pct_place] + \ |
75 |
| - (pct_string + self.prog_bar[pct_place + len(pct_string):]) |
76 |
| - |
77 |
| - def __str__(self): |
78 |
| - return str(self.prog_bar) |
| 54 | + num_hashes = int(percent/100 * all_full) |
| 55 | + |
| 56 | + bar = self.fill_char * num_hashes + ' ' * (all_full - num_hashes) |
| 57 | + |
| 58 | + info = '%d%%' % percent |
| 59 | + loc = ( len(bar) - len(info) )/2 |
| 60 | + return replace_at(bar, info, loc, loc + len(info)) |
| 61 | + |
| 62 | + |
| 63 | +def replace_at(str, new, start, stop): |
| 64 | + return str[:start] + new + str[stop:] |
| 65 | + |
| 66 | +def consoleprint(s): |
| 67 | + if sys.platform.lower().startswith('win'): |
| 68 | + print(s, '\r', end='') |
| 69 | + else: |
| 70 | + print(s) |
| 71 | + |
| 72 | +def ipythonprint(s): |
| 73 | + print('\r', s, end='') |
| 74 | + sys.stdout.flush() |
| 75 | + |
| 76 | +class IPythonNotebookPB(ProgressBar): |
| 77 | + def __init__(self, iterations): |
| 78 | + self.divid = str(uuid.uuid4()) |
| 79 | + self.sec_id = str(uuid.uuid4()) |
| 80 | + |
| 81 | + pb = HTML( |
| 82 | + """ |
| 83 | + <div style="float: left; border: 1px solid black; width:500px"> |
| 84 | + <div id="%s" style="background-color:blue; width:0%%"> </div> |
| 85 | + </div> |
| 86 | + <label id="%s" style="padding-left: 10px;" text = ""/> |
| 87 | + """ % (self.divid,self.sec_id)) |
| 88 | + display(pb) |
| 89 | + |
| 90 | + ProgressBar.__init__(self, iterations) |
| 91 | + |
| 92 | + def animate(self, i, elapsed): |
| 93 | + percentage = int(self.fraction(i)) |
| 94 | + |
| 95 | + display(Javascript("$('div#%s').width('%i%%')" % (self.divid, percentage))) |
| 96 | + display(Javascript("$('label#%s').text('%i%% in %.1f sec')" % (self.sec_id, fraction, round(elapsed, 1)))) |
| 97 | + |
| 98 | +def run_from_ipython(): |
| 99 | + try: |
| 100 | + __IPYTHON__ |
| 101 | + return True |
| 102 | + except NameError: |
| 103 | + return False |
| 104 | + |
| 105 | +def progress_bar(iters): |
| 106 | + if run_from_ipython(): |
| 107 | + if in_notebook(): |
| 108 | + return NotebookProgressBar(iters) |
| 109 | + else: |
| 110 | + return IPythonConsolePB(iters, ipythonprint) |
| 111 | + else: |
| 112 | + return TextProgressBar(iters, consoleprint) |
0 commit comments