Incremental GSC parsing (exact copy of the tutorials shared as a separate project) / tqdm / _tqdm_gui.py
1576 views"""1GUI progressbar decorator for iterators.2Includes a default (x)range iterator printing to stderr.34Usage:5>>> from tqdm_gui import tgrange[, tqdm_gui]6>>> for i in tgrange(10): #same as: for i in tqdm_gui(xrange(10))7... ...8"""9# future division is important to divide integers and get as10# a result precise floating numbers (instead of truncated int)11from __future__ import division, absolute_import12# import compatibility functions and utilities13import sys14from time import time15from ._utils import _range16# to inherit from the tqdm class17from ._tqdm import tqdm181920__author__ = {"github.com/": ["casperdcl", "lrq3000"]}21__all__ = ['tqdm_gui', 'tgrange']222324class tqdm_gui(tqdm): # pragma: no cover25"""26Experimental GUI version of tqdm!27"""2829@classmethod30def write(cls, s, file=sys.stdout, end="\n"):31"""32Print a message via tqdm_gui (just an alias for print)33"""34# TODO: print text on GUI?35file.write(s)36file.write(end)3738def __init__(self, *args, **kwargs):39import matplotlib as mpl40import matplotlib.pyplot as plt41from collections import deque42kwargs['gui'] = True4344super(tqdm_gui, self).__init__(*args, **kwargs)4546# Initialize the GUI display47if self.disable or not kwargs['gui']:48return4950self.fp.write('Warning: GUI is experimental/alpha\n')51self.mpl = mpl52self.plt = plt53self.sp = None5455# Remember if external environment uses toolbars56self.toolbar = self.mpl.rcParams['toolbar']57self.mpl.rcParams['toolbar'] = 'None'5859self.mininterval = max(self.mininterval, 0.5)60self.fig, ax = plt.subplots(figsize=(9, 2.2))61# self.fig.subplots_adjust(bottom=0.2)62if self.total:63self.xdata = []64self.ydata = []65self.zdata = []66else:67self.xdata = deque([])68self.ydata = deque([])69self.zdata = deque([])70self.line1, = ax.plot(self.xdata, self.ydata, color='b')71self.line2, = ax.plot(self.xdata, self.zdata, color='k')72ax.set_ylim(0, 0.001)73if self.total:74ax.set_xlim(0, 100)75ax.set_xlabel('percent')76self.fig.legend((self.line1, self.line2), ('cur', 'est'),77loc='center right')78# progressbar79self.hspan = plt.axhspan(0, 0.001,80xmin=0, xmax=0, color='g')81else:82# ax.set_xlim(-60, 0)83ax.set_xlim(0, 60)84ax.invert_xaxis()85ax.set_xlabel('seconds')86ax.legend(('cur', 'est'), loc='lower left')87ax.grid()88# ax.set_xlabel('seconds')89ax.set_ylabel((self.unit if self.unit else 'it') + '/s')90if self.unit_scale:91plt.ticklabel_format(style='sci', axis='y',92scilimits=(0, 0))93ax.yaxis.get_offset_text().set_x(-0.15)9495# Remember if external environment is interactive96self.wasion = plt.isinteractive()97plt.ion()98self.ax = ax99100def __iter__(self):101# TODO: somehow allow the following:102# if not self.gui:103# return super(tqdm_gui, self).__iter__()104iterable = self.iterable105if self.disable:106for obj in iterable:107yield obj108return109110# ncols = self.ncols111mininterval = self.mininterval112maxinterval = self.maxinterval113miniters = self.miniters114dynamic_miniters = self.dynamic_miniters115unit = self.unit116unit_scale = self.unit_scale117ascii = self.ascii118start_t = self.start_t119last_print_t = self.last_print_t120last_print_n = self.last_print_n121n = self.n122# dynamic_ncols = self.dynamic_ncols123smoothing = self.smoothing124avg_time = self.avg_time125bar_format = self.bar_format126127plt = self.plt128ax = self.ax129xdata = self.xdata130ydata = self.ydata131zdata = self.zdata132line1 = self.line1133line2 = self.line2134135for obj in iterable:136yield obj137# Update and print the progressbar.138# Note: does not call self.update(1) for speed optimisation.139n += 1140delta_it = n - last_print_n141# check the counter first (avoid calls to time())142if delta_it >= miniters:143cur_t = time()144delta_t = cur_t - last_print_t145if delta_t >= mininterval:146elapsed = cur_t - start_t147# EMA (not just overall average)148if smoothing and delta_t:149avg_time = delta_t / delta_it \150if avg_time is None \151else smoothing * delta_t / delta_it + \152(1 - smoothing) * avg_time153154# Inline due to multiple calls155total = self.total156# instantaneous rate157y = delta_it / delta_t158# overall rate159z = n / elapsed160# update line data161xdata.append(n * 100.0 / total if total else cur_t)162ydata.append(y)163zdata.append(z)164165# Discard old values166# xmin, xmax = ax.get_xlim()167# if (not total) and elapsed > xmin * 1.1:168if (not total) and elapsed > 66:169xdata.popleft()170ydata.popleft()171zdata.popleft()172173ymin, ymax = ax.get_ylim()174if y > ymax or z > ymax:175ymax = 1.1 * y176ax.set_ylim(ymin, ymax)177ax.figure.canvas.draw()178179if total:180line1.set_data(xdata, ydata)181line2.set_data(xdata, zdata)182try:183poly_lims = self.hspan.get_xy()184except AttributeError:185self.hspan = plt.axhspan(0, 0.001, xmin=0,186xmax=0, color='g')187poly_lims = self.hspan.get_xy()188poly_lims[0, 1] = ymin189poly_lims[1, 1] = ymax190poly_lims[2] = [n / total, ymax]191poly_lims[3] = [poly_lims[2, 0], ymin]192if len(poly_lims) > 4:193poly_lims[4, 1] = ymin194self.hspan.set_xy(poly_lims)195else:196t_ago = [cur_t - i for i in xdata]197line1.set_data(t_ago, ydata)198line2.set_data(t_ago, zdata)199200ax.set_title(self.format_meter(201n, total, elapsed, 0,202self.desc, ascii, unit, unit_scale,2031 / avg_time if avg_time else None, bar_format),204fontname="DejaVu Sans Mono", fontsize=11)205plt.pause(1e-9)206207# If no `miniters` was specified, adjust automatically208# to the maximum iteration rate seen so far.209if dynamic_miniters:210if maxinterval and delta_t > maxinterval:211# Set miniters to correspond to maxinterval212miniters = delta_it * maxinterval / delta_t213elif mininterval and delta_t:214# EMA-weight miniters to converge215# towards the timeframe of mininterval216miniters = smoothing * delta_it * mininterval \217/ delta_t + (1 - smoothing) * miniters218else:219miniters = smoothing * delta_it + \220(1 - smoothing) * miniters221222# Store old values for next call223last_print_n = n224last_print_t = cur_t225226# Closing the progress bar.227# Update some internal variables for close().228self.last_print_n = last_print_n229self.n = n230self.close()231232def update(self, n=1):233# if not self.gui:234# return super(tqdm_gui, self).close()235if self.disable:236return237238if n < 0:239n = 1240self.n += n241242delta_it = self.n - self.last_print_n # should be n?243if delta_it >= self.miniters:244# We check the counter first, to reduce the overhead of time()245cur_t = time()246delta_t = cur_t - self.last_print_t247if delta_t >= self.mininterval:248elapsed = cur_t - self.start_t249# EMA (not just overall average)250if self.smoothing and delta_t:251self.avg_time = delta_t / delta_it \252if self.avg_time is None \253else self.smoothing * delta_t / delta_it + \254(1 - self.smoothing) * self.avg_time255256# Inline due to multiple calls257total = self.total258ax = self.ax259260# instantaneous rate261y = delta_it / delta_t262# smoothed rate263z = self.n / elapsed264# update line data265self.xdata.append(self.n * 100.0 / total266if total else cur_t)267self.ydata.append(y)268self.zdata.append(z)269270# Discard old values271if (not total) and elapsed > 66:272self.xdata.popleft()273self.ydata.popleft()274self.zdata.popleft()275276ymin, ymax = ax.get_ylim()277if y > ymax or z > ymax:278ymax = 1.1 * y279ax.set_ylim(ymin, ymax)280ax.figure.canvas.draw()281282if total:283self.line1.set_data(self.xdata, self.ydata)284self.line2.set_data(self.xdata, self.zdata)285try:286poly_lims = self.hspan.get_xy()287except AttributeError:288self.hspan = self.plt.axhspan(0, 0.001, xmin=0,289xmax=0, color='g')290poly_lims = self.hspan.get_xy()291poly_lims[0, 1] = ymin292poly_lims[1, 1] = ymax293poly_lims[2] = [self.n / total, ymax]294poly_lims[3] = [poly_lims[2, 0], ymin]295if len(poly_lims) > 4:296poly_lims[4, 1] = ymin297self.hspan.set_xy(poly_lims)298else:299t_ago = [cur_t - i for i in self.xdata]300self.line1.set_data(t_ago, self.ydata)301self.line2.set_data(t_ago, self.zdata)302303ax.set_title(self.format_meter(304self.n, total, elapsed, 0,305self.desc, self.ascii, self.unit, self.unit_scale,3061 / self.avg_time if self.avg_time else None,307self.bar_format),308fontname="DejaVu Sans Mono", fontsize=11)309self.plt.pause(1e-9)310311# If no `miniters` was specified, adjust automatically to the312# maximum iteration rate seen so far.313# e.g.: After running `tqdm.update(5)`, subsequent314# calls to `tqdm.update()` will only cause an update after315# at least 5 more iterations.316if self.dynamic_miniters:317if self.maxinterval and delta_t > self.maxinterval:318self.miniters = self.miniters * self.maxinterval \319/ delta_t320elif self.mininterval and delta_t:321self.miniters = self.smoothing * delta_it \322* self.mininterval / delta_t + \323(1 - self.smoothing) * self.miniters324else:325self.miniters = self.smoothing * delta_it + \326(1 - self.smoothing) * self.miniters327328# Store old values for next call329self.last_print_n = self.n330self.last_print_t = cur_t331332def close(self):333# if not self.gui:334# return super(tqdm_gui, self).close()335if self.disable:336return337338self.disable = True339340self._instances.remove(self)341342# Restore toolbars343self.mpl.rcParams['toolbar'] = self.toolbar344# Return to non-interactive mode345if not self.wasion:346self.plt.ioff()347if not self.leave:348self.plt.close(self.fig)349350351def tgrange(*args, **kwargs):352"""353A shortcut for tqdm_gui(xrange(*args), **kwargs).354On Python3+ range is used instead of xrange.355"""356return tqdm_gui(_range(*args), **kwargs)357358359