diff --git a/package/MDAnalysis/lib/log.py b/package/MDAnalysis/lib/log.py index a063878bd57..74b2609a1d3 100644 --- a/package/MDAnalysis/lib/log.py +++ b/package/MDAnalysis/lib/log.py @@ -176,57 +176,161 @@ def emit(self, record): pass -def echo(s='', replace=False, newline=True): - r"""Simple string output that immediately prints to the console. +class ProgressBar(tqdm): + r"""Display a visual progress bar and time estimate. + + The :class:`ProgressBar` decorates an iterable object, returning an + iterator which acts exactly like the original iterable, but prints a + dynamically updating progressbar every time a value is requested. See the + example below for how to use it when iterating over the frames of a + trajectory. - The string `s` is modified according to the keyword arguments and then - printed to :const:`sys.stderr`, which is immediately flushed. Parameters ---------- - s : str - The string to output. - replace : bool - If ``True``, the string will be printed on top of the current line. In - practice, ``\r`` is added at the beginning of the string. - newline : bool - If ``True``, a newline is added at the end of the string. - - """ - if replace: - s = '\r' + s - if newline: - end='\n' - else: - end='' - print(s, file=sys.stderr, end=end) - sys.stderr.flush() - - -def _new_format(template, variables): - """Format a string that follows the {}-based syntax. - """ - return template.format(**variables) - + iterable : iterable, optional + Iterable to decorate with a progressbar. + Leave blank to manually manage the updates. + verbose : bool, optional + If ``True`` (the default) then show the progress bar, *unless* the + `disable` keyword is set to ``True`` (`disable` takes precedence over + `verbose`). If `verbose` is set to ``None`` then the progress bar is + displayed (like ``True``), *unless* this is a non-TTY output device + (see `disable`). + desc : str, optional + Prefix for the progressbar. + total : int or float, optional + The number of expected iterations. If unspecified, + ``len(iterable)`` is used if possible. If ``float("inf")`` or as a last + resort, only basic progress statistics are displayed + (no ETA, no progressbar). + leave : bool, optional + If [default: ``True``], keeps all traces of the progressbar + upon termination of iteration. + If ``None``, will leave only if `position` is 0. + file : :class:`io.TextIOWrapper` or :class:`io.StringIO`, optional + Specifies where to output the progress messages (default: + :data:`sys.stderr`). Uses :meth:`file.write` and :meth:`file.flush` + methods. For encoding, see `write_bytes`. + ncols : int, optional + The width of the entire output message. If specified, + dynamically resizes the progressbar to stay within this bound. + If unspecified, attempts to use environment width. The + fallback is a meter width of 10 and no limit for the counter and + statistics. If 0, will not print any meter (only stats). + mininterval : float, optional + Minimum progress display update interval [default: 0.1] seconds. + maxinterval : float, optional + Maximum progress display update interval [default: 10] seconds. + Automatically adjusts `miniters` to correspond to `mininterval` + after long display update lag. Only works if `dynamic_miniters` + or monitor thread is enabled. + miniters : int or float, optional + Minimum progress display update interval, in iterations. + If 0 and `dynamic_miniters`, will automatically adjust to equal + `mininterval` (more CPU efficient, good for tight loops). + If > 0, will skip display of specified number of iterations. + Tweak this and `mininterval` to get very efficient loops. + If your progress is erratic with both fast and slow iterations + (network, skipping items, etc) you should set miniters=1. + ascii : bool or str, optional + If unspecified or ``False``, use unicode (smooth blocks) to fill + the meter. The fallback is to use ASCII characters " 123456789#". + disable : bool, optional + Whether to disable the entire progressbar wrapper + [default: ``False``]. If set to None, disable on non-TTY. + unit : str, optional + String that will be used to define the unit of each iteration + [default: it]. + unit_scale : bool or int or float, optional + If 1 or True, the number of iterations will be reduced/scaled + automatically and a metric prefix following the + International System of Units standard will be added + (kilo, mega, etc.) [default: ``False``]. If any other non-zero + number, will scale `total` and `n`. + dynamic_ncols : bool, optional + If set, constantly alters `ncols` and `nrows` to the + environment (allowing for window resizes) [default: ``False``]. + smoothing : float, optional + Exponential moving average smoothing factor for speed estimates + (ignored in GUI mode). Ranges from 0 (average speed) to 1 + (current/instantaneous speed) [default: 0.3]. + bar_format : str, optional + Specify a custom bar string formatting. May impact performance. + [default: ``'{l_bar}{bar}{r_bar}'``], where ``l_bar='{desc}: + {percentage:3.0f}%|'`` and ``r_bar='| {n_fmt}/{total_fmt} + [{elapsed}<{remaining}, {rate_fmt}{postfix}]'`` + + Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt, + percentage, elapsed, elapsed_s, ncols, nrows, desc, unit, + rate, rate_fmt, rate_noinv, rate_noinv_fmt, + rate_inv, rate_inv_fmt, postfix, unit_divisor, + remaining, remaining_s. + + Note that a trailing ": " is automatically removed after {desc} + if the latter is empty. + initial : int or float, optional + The initial counter value. Useful when restarting a progress bar + [default: 0]. If using :class:`float`, consider specifying ``{n:.3f}`` + or similar in `bar_format`, or specifying `unit_scale`. + position : int, optional + Specify the line offset to print this bar (starting from 0) + Automatic if unspecified. + Useful to manage multiple bars at once (e.g., from threads). + postfix : dict or \*, optional + Specify additional stats to display at the end of the bar. + Calls ``set_postfix(**postfix)`` if possible (:class:`dict`). + unit_divisor : float, optional + [default: 1000], ignored unless `unit_scale` is ``True``. + write_bytes : bool, optional + If (default: ``None``) and `file` is unspecified, + bytes will be written in Python 2. If `True` will also write + bytes. In all other cases will default to unicode. + lock_args : tuple, optional + Passed to `refresh` for intermediate output + (initialisation, iterating, and updating). + nrows : int, optional + The screen height. If specified, hides nested bars outside this + bound. If unspecified, attempts to use environment height. + The fallback is 20. + + Returns + ------- + out : decorated iterator. + + Example + ------- + To get a progress bar when analyzing a trajectory:: + + from MDAnalysis.lib.log import ProgressBar + + ... + + for ts in ProgressBar(u.trajectory): + # perform analysis + + + will produce something similar to :: + + 30%|███████████████ | 3/10 [00:13<00:30, 4.42s/it] + + in a terminal or Jupyter notebook. + + + See Also + -------- + The :class:`ProgressBar` is derived from :class:`tqdm.auto.tqdm`; see the + `tqdm documentation`_ for further details on how to use it. + + + + .. _`tqdm documentation`: https://tqdm.github.io/ -def _legacy_format(template, variables): - """Format a string that follows the %-based syntax. """ - return template % variables - - -def _guess_string_format(template): - """Guess if the template follow {}-based or %-based syntax. - """ - match = re.search(r'%\((step|numsteps|percentage)\)', template) - if match is None: - return _new_format - else: - return _legacy_format - - -class ProgressBar(tqdm): def __init__(self, *args, **kwargs): + """""" + # ^^^^ keep the empty doc string to avoid Sphinx doc errors with the + # original doc string from tqdm.auto.tqdm verbose = kwargs.pop('verbose', True) # disable: Whether to disable the entire progressbar wrapper [default: False]. # If set to None, disable on non-TTY.