Git Product home page Git Product logo

pyprind's Introduction

Build Status Coverage Status Python 2.7 Python 3 License

PyPrind (Python Progress Indicator)

The PyPrind (Python Progress Indicator) module provides a progress bar and a percentage indicator object that let you track the progress of a loop structure or other iterative computation.
Typical applications include the processing of large data sets to provide an intuitive estimate at runtime about the progress of the computation.

PyPrind Demo


Progress Bars and Percentage Generators

import pyprind

for i in pyprind.prog_bar(range(n)):
    time.sleep(timesleep) # your computation here
0%                          100%
[##############################] | ETA: 00:00:00
Total time elapsed: 00:00:05


for i in pyprind.prog_percent(range(n)):
    time.sleep(timesleep) # your computation here
[10 %] Time elapsed: 00:00:01 | ETA: 00:00:04

While-loops

The ProgBar and ProgPercent classes also support while loops if desired. The objects are updated inside the loop using the update method as shown below:

import random
import pyprind
import time

timesleep = 0.05
random.seed(1)
collection = set()

n = 100
bar = pyprind.ProgBar(n, track_time=False, title='while example')

while len(collection) < n:
    r = random.randint(0, 10**5)
    if r % 7 and r not in collection:
        collection.add(r)
        bar.update()
        time.sleep(timesleep)

print(bar)
while example
0%                          100%
[##############################]
Title: while example
  Started: 09/07/2016 13:06:58
  Finished: 09/07/2016 13:07:03
  Total time elapsed: 00:00:05


If you have the psutil package installed, you can set the monitor=True to track CPU and memory usage:

bar = pyprind.ProgBar(n, monitor=True)
for i in range(n):
    time.sleep(timesleep) # your computation here
    bar.update()
print(bar)
0%                          100%
[##############################] | ETA: 00:00:00
Total time elapsed: 00:00:05
Title:
  Started: 09/07/2016 13:14:09
  Finished: 09/07/2016 13:14:14
  Total time elapsed: 00:00:05
  CPU %: 1.90
  Memory %: 0.48


Choose Your Favorite Bar Style

bar = pyprind.ProgBar(n, bar_char='█')
for i in range(n):
    time.sleep(0.1) # do some computation
    bar.update()
0%                          100%
[██████████████████████████████] | ETA: 00:00:00
Total time elapsed: 00:00:10

Note to PyCharm users

If you are using the PyCharm IDE, you need to pass the sys.stdout or sys.err as a stream argument to display the progress indicators correctly in the IDE. For example,

import sys

bar = pyprind.ProgBar(n, stream=sys.stdout)
for i in range(n):
    time.sleep(0.1) # do some computation
    bar.update()


###View more examples in an IPython Demo Notebook






Installation

[back to top]

The most convenient way to install PyPrind is via tools like pip or easy_install:

  • pip install pyprind

  • easy_install pyprind

PyPrind comes without any dependencies except for the optional psutil to monitor CPU and memory usages. You can install psutil via pip install psutil or install it automatically with PyPrind:
pip install pyprind -r requirements.txt

Alternatively, you can install PyPrind the classic way: Download the package from the Python Package Index https://pypi.python.org/pypi/PyPrind, unzip it, navigate into the unzipped directory, and use the command

python setup.py install




Documentation

[back to top]

PyPrind consists of two class objects that can visualize the progress of a computation on the output screen.
Progress bars are available via ProgBar, and percentage indicators can be used via a ProgPercent.

	n = 10000000
	bar = pyprind.ProgBar(n)   # 1) initialization with number of iterations
	for i in range(n):
    	# do some computation
    	bar.update()           # 2) update the progress visualization

Alternatively, the progress can be tracked via the equivalent generator functions prog_bar and prog_percent:

	for i in pyprind.prog_bar(range(n)):
    	# do something
    	pass

Complete Parameter of Parameters and Options

ProgBar

ProgBar(iterations, track_time=True, width=30, bar_char='#', stream=2, title='', monitor=False, update_interval=None))

  • iterations : int
    Number of iterations for the iterative computation.
  • track_time : bool (default: True)
    Prints elapsed time when loop has finished.
  • width : int (default: 30)
    Sets the progress bar width in characters.
  • stream : int (default: 2).
    Setting the output stream. Takes 1 for stdout, 2 for stderr, or a custom stream object
  • title : str (default: '')
    Setting a title for the progress bar.
  • monitor : bool (default: False)
    Monitors CPU and memory usage if True (requires psutil package).
  • update_interval : float or int (default: None)
    The update_interval in seconds controls how often the progress is flushed to the screen. Automatic mode if update_interval=None.
ProgPercent

ProgPercent(iterations, track_time=True, stream=2, title='', monitor=False, update_interval=None)

  • iterations : int
    Number of iterations for the iterative computation.
  • track_time : bool (default: True)
    Prints elapsed time when loop has finished.
  • stream : int (default: 2).
    Setting the output stream. Takes 1 for stdout, 2 for stderr, or a custom stream object
  • title : str (default : '').
    Setting a title for the percentage indicator.
  • monitor : bool (default: False)
    Monitors CPU and memory usage if True (requires psutil package).
  • update_interval : float or int (default: None)
    The update_interval in seconds controls how often the progress is flushed to the screen. Automatic mode if update_interval=None.
update method

update(iterations=1, item_id=None, force_flush=False)

  • iterations : int (default: 1)
    default argument can be changed to integer values >=1 in order to update the progress indicators more than once per iteration.
  • item_id : str (default: None)
    Print an item_id sring behind the progress bar
  • force_flush : bool (default: False)
    If True, flushes the progress indicator to the output screen in each iteration.




Examples

[back to top]

Examples for using the progress bar and percentage indicator objects can be found in the IPython Demo Notebook.




pyprind's People

Contributors

bluewoodtree avatar cvanelteren avatar div44 avatar eeeeeric avatar ericdill avatar hwmrocker avatar koobs avatar ktolstikhin avatar maikelwever avatar msabramo avatar rasbt avatar taylan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyprind's Issues

Not working in while statement

import random
import pyprind
random.seed(1)
collection = set()
import time
n = 100
bar = pyprind.ProgBar(n, track_time=False, title='while example')
i=0
while i < n:
r = random.randint(0, 10**5)
if r % 7 and r not in collection:
collection.add(r)
bar.update()
i=i+10
time.sleep(0.04)
The code above does not work. Please give me some advice, thanks.
while example
0% [### ] 100%

Missing 2.9.5 repository tag

Version 2.9.5 has been published to PyPI but there is no corresponding 2.9.5 repository tag for the revision from which the release was made.

pip doesn't respect `requires`

Hi Sebastien-

Thanks for this awesome library.

Pip 1.5.6 and pip 6.1.1 don't respect requires in setup.py (Tried on 2.7 and 3.4). It seems like this needs to be install_requires to get psutil included as a dependency when using pip to install.

Update ETA more frequently than the bar

The following example shows a default progress bar that takes a long time to complete. The problem is that the ETA value is only updated when the progress bar advances:

import pyprind
import time
amount = 80000
bar = pyprind.ProgBar(amount, width=10)
for i in enumerate(range(amount)):
  time.sleep(.1) # some op
  bar.update()

I'd like a more frequent ETA update. I'm interested less in the bar graph. To work around this, I can set bar width to 1000, this redraws the bar more often and thus gives me a usable ETA calculation too.

Perhaps the redrawing frequency of the bar and ETA can be decoupled?

pip install faliure - requirements.txt not existing

Hi there,

If I do pip install pyprind (a pip from anaconda - don't know if that matters), it errors out with:

error: can't copy 'requirements.txt': doesn't exist or not a regular file

    ----------------------------------------
Command "//anaconda/bin/python3 -c "import setuptools, tokenize;__file__='/private/var/folders/7z/r5scjljn7l10_fp021tw5wy40000gn/T/pip-build-i3wcyy5u/pyprind/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /var/folders/7z/r5scjljn7l10_fp021tw5wy40000gn/T/pip-h8ccuqqx-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /private/var/folders/7z/r5scjljn7l10_fp021tw5wy40000gn/T/pip-build-i3wcyy5u/pyprind

I think in the setup.py in L13 there is specified a requirements.txt which is actually not there.
Am I doing it wrong?

Support for progress bar based on arbitrary position (e.g. file position)

I'm trying to use pyprint to add a progress bar for processing a large textfile.

My understanding is that that pypring needs the total number of loop iterations before-hand, in order to calculate the progress bars.

However, if you just have a large textfile, there is no way of telling how many lines there are without actually reading through the whole file.

It would be nice if there was some way of setting a progress bar, such that you could give it a total file-size, then update it with the current progress through the file - e.g.

import pyprind
import os
import time
n = os.path.getsize('queries.txt')

bar = pyprind.ProgBar(n)
with open('queries.txt', 'r') as f:
    for line in f:
        time.sleep(0.5)
        # do some computation
        # Use f.tell() for current position - pass to bar, somehow
        bar.update()

Debian packaging in progress

Hi!

This is a friendly notice to let you know that Debian is working on packaging your software for Debian. You can follow the progress of that work in bug #867800 in the Debian Bug Tracking System (BTS).

The source code for the Debian package is in this git repository. It will be uploaded into Debian shortly, at which point it will end up in the NEW queue for legal review. Once the NEW process is completed, it takes about 10 days for the package to trickle down into "testing", which will become the next Debian release. This means your software will eventually be shipped in a "long term support" release, which last from three to five years, according to the current statistics.

If you are interested in maintaining the package yourself upstream, that is definitely possible. You can either upload the package yourself if you are a Debian member or I can act as a sponsor when a new release is published.

This is just a notification, but can also act as a coordination point for upstream packaging if you wish to followup on this. otherwise, feel free to close this issue whenever you like.

Writing the progress to a log file

I think in certain settings, it would be useful to redirect the progress bar/percentage to a log file (for example, if we are running scripts remotely and don't want to maintain a screen session.

An optional argument could be added that accepts a valid file path, e.g.,

ProgBar(..., logfile='path/to/logfile.log') 
ProgPercent(..., logfile='path/to/logfile.log') 

Using double progressbars?

Hi. Thx for this package. I've one question:
How can i use 2 progressbars at same time? One for main loop, second for subloop?
For example file copy utility (like in FAR):
1 progressbar shows how many files ramained
2 progressbar shows file copy progress

I've tryed to simply add second bar inside first bar loop

    n = 10
    items = ['file_%s.csv' %i for i in range(1,10)]

    bar = pyprind.ProgBar(len(items))
    for i in items:
        bar.update(item_id = i)
        for z in pyprind.prog_percent(range(n), monitor=True):
            time.sleep(0.1) # do some computation

    print bar

here is output

0%     100%
[100 %] elapsed[sec]: 1.099 | ETA[sec]: 0.000
Total time elapsed: 1.099 sec
[100 %] elapsed[sec]: 1.095 | ETA[sec]: 0.000 2.csv
Total time elapsed: 1.095 sec
[100 %] elapsed[sec]: 1.099 | ETA[sec]: 0.000 3.csv
Total time elapsed: 1.099 sec
[100 %] elapsed[sec]: 1.099 | ETA[sec]: 0.000 4.csv
Total time elapsed: 1.099 sec
[100 %] elapsed[sec]: 1.102 | ETA[sec]: 0.000 5.csv
Total time elapsed: 1.102 sec
[100 %] elapsed[sec]: 1.100 | ETA[sec]: 0.000 6.csv
Total time elapsed: 1.100 sec
[100 %] elapsed[sec]: 1.105 | ETA[sec]: 0.000 7.csv
Total time elapsed: 1.105 sec
[100 %] elapsed[sec]: 1.100 | ETA[sec]: 0.000 8.csv
Total time elapsed: 1.100 sec
[#########] | ETA[sec]: 0.000 | Item ID: file_9.csv
Total time elapsed: 8.799 sec
[100 %] elapsed[sec]: 1.086 | ETA[sec]: 0.000
Total time elapsed: 1.086 sec
Title:
  Started: 12/13/2015 00:20:42
  Finished: 12/13/2015 00:20:51
  Total time elapsed: 8.799 sec

this is not what i exspected to see :)

psutil dependency missing on PyPi

Hi!

First of all, thanks for this amazing module! It looks really nice and is simple to use :)

Second, I usually install this with Pip (because why not?), but unfortunately, when I use it, psutil is always missing. When I install that too, it works fine. I believe you should specify this as a dependency. I am no Pip expert, so I don't know how, unfortunately.

pyprind ProgBar monitor=True fails

I tried to use pyprind to see the progress of reading a big file, and it works really nicely with monitor=False, but doesn't work if I use monitor=True:

my_bar = pyprind.ProgBar(line_cnt, stream=1, width=30, track_time=True, title='Reading Input File', monitor=True)
File "/usr/local/lib/python2.7/dist-packages/pyprind/progbar.py", line 27, in __init__
Prog.__init__(self, iterations, track_time, stream, title, monitor)
File "/usr/local/lib/python2.7/dist-packages/pyprind/prog_class.py", line 24, in __init__
import psutil

Here is my source:

d = np.array([])
## setup the progress bar indicator
line_cnt = subprocess.check_output(['wc', '-l', input_file])
line_cnt = int(line_cnt.split()[0])
my_bar = pyprind.ProgBar(line_cnt, stream=1, width=30, track_time=True, title='Reading Input File', monitor=False)

## read the inputfile into a numpy array
with open(input_file, 'r') as fp:
    for line in fp:
        d = np.append(d, line.strip())
        my_bar.update()
print(d.shape)

psutil requirement

HI,
I am working with a package that uses pyprind and seems that there is a prob with psutil.
Also doing

pip install pyprind -r requirements.txt
Could not open requirements file: [Errno 2] No such file or directory: 'requirements.txt'

looks like there is no 'requirements.txt' and this prevents pyprind to work


bw2setup()
bw2setup()
Creating default biosphere

Writing activities to SQLite3 database:
Applying strategy: normalize_units
Applying strategy: drop_unspecified_subcategories
Applied 2 strategies in 0.01 seconds
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-5-c9438012d7c9> in <module>()
----> 1 bw2setup()

/home/giuseppe/miniconda2/envs/bw2/lib/python3.4/site-packages/bw2io/__init__.py in bw2setup()
     90         return
     91     print("Creating default biosphere\n")
---> 92     create_default_biosphere3()
     93     print("Creating default LCIA methods\n")
     94     create_default_lcia_methods()

/home/giuseppe/miniconda2/envs/bw2/lib/python3.4/site-packages/bw2io/__init__.py in create_default_biosphere3()
     77     eb = Ecospold2BiosphereImporter()
     78     eb.apply_strategies()
---> 79     eb.write_database()
     80 
     81 def create_default_lcia_methods():

/home/giuseppe/miniconda2/envs/bw2/lib/python3.4/site-packages/bw2io/importers/base_lci.py in write_database(self, data, name, overwrite, backend, **kwargs)
     96         data = {(ds['database'], ds['code']): ds for ds in data}
     97         existing.update(data)
---> 98         db.write(existing)
     99         print("Created database: {}".format(db.name))
    100         return db

/home/giuseppe/miniconda2/envs/bw2/lib/python3.4/site-packages/bw2data/project.py in writable_project(wrapped, instance, args, kwargs)
    316     if projects.read_only:
    317         raise ReadOnlyProject(READ_ONLY_PROJECT)
--> 318     return wrapped(*args, **kwargs)

/home/giuseppe/miniconda2/envs/bw2/lib/python3.4/site-packages/bw2data/backends/peewee/database.py in write(self, data, process)
    228         if data:
    229             try:
--> 230                 self._efficient_write_many_data(data)
    231             except:
    232                 # Purge all data from database, then reraise

/home/giuseppe/miniconda2/envs/bw2/lib/python3.4/site-packages/bw2data/backends/peewee/database.py in _efficient_write_many_data(self, data, indices)
    150                     len(data),
    151                     title="Writing activities to SQLite3 database:",
--> 152                     monitor=True
    153                 )
    154 

/home/giuseppe/miniconda2/envs/bw2/lib/python3.4/site-packages/pyprind/progbar.py in __init__(self, iterations, track_time, width, bar_char, stream, title, monitor, update_interval)
     46                  stream=2, title='', monitor=False, update_interval=None):
     47         Prog.__init__(self, iterations, track_time,
---> 48                       stream, title, monitor, update_interval)
     49         self.bar_width = width
     50         self._adjust_width()

/home/giuseppe/miniconda2/envs/bw2/lib/python3.4/site-packages/pyprind/prog_class.py in __init__(self, iterations, track_time, stream, title, monitor, update_interval)
     42 
     43         if self.monitor:
---> 44             import psutil
     45             self.process = psutil.Process()
     46         if self.track:

ImportError: No module named 'psutil'

Lines joined when running pyprind alongside the logging module

Hi!

I was trying to run both pyprind and the builtin python module logging at the same time. This, however did not handle particularly well:

import time
import pyprind
import logging

logging.basicConfig(level=logging.INFO)

n = 15

bar = pyprind.ProgPercent(n)
for i in range(n):
        time.sleep(1)
        bar.update()
        logging.info("Something happened.")

The output looks like this:

[  6 %] Time elapsed: 00:00:01 | ETA: 00:00:14INFO:root:Something happened.
[ 13 %] Time elapsed: 00:00:02 | ETA: 00:00:13INFO:root:Something happened.
[ 20 %] Time elapsed: 00:00:03 | ETA: 00:00:12INFO:root:Something happened.
[ 26 %] Time elapsed: 00:00:04 | ETA: 00:00:11INFO:root:Something happened.
[ 33 %] Time elapsed: 00:00:05 | ETA: 00:00:10INFO:root:Something happened.
[ 40 %] Time elapsed: 00:00:06 | ETA: 00:00:09INFO:root:Something happened.
[ 46 %] Time elapsed: 00:00:07 | ETA: 00:00:08INFO:root:Something happened.
[ 53 %] Time elapsed: 00:00:08 | ETA: 00:00:07INFO:root:Something happened.
[ 60 %] Time elapsed: 00:00:09 | ETA: 00:00:06INFO:root:Something happened.
[ 66 %] Time elapsed: 00:00:10 | ETA: 00:00:05INFO:root:Something happened.
[ 73 %] Time elapsed: 00:00:11 | ETA: 00:00:04INFO:root:Something happened.
[ 80 %] Time elapsed: 00:00:12 | ETA: 00:00:03INFO:root:Something happened.
[ 86 %] Time elapsed: 00:00:13 | ETA: 00:00:02INFO:root:Something happened.
[ 93 %] Time elapsed: 00:00:14 | ETA: 00:00:01INFO:root:Something happened.
[100 %] Time elapsed: 00:00:15 | ETA: 00:00:00
Total time elapsed: 00:00:15
INFO:root:Something happened.

As you see, the lines from pyprind and logging are joined. This is somewhat random in a real world scenario, but happens most of the time.

I have not yet found any fix or workaround. Any ideas?

pyprind with theano, numpy, CUDA, etc.

Hi folks,

thanks for your great library, I love it. However, when working with Theano, CUDA or numpy the pyprind progress bar doesn't seem to work (if i remove e.g. the numpy computation it works fine).
What happens: I have to set a manual interval to force an update, but mostly it is not updated. Anyone having similar experience?

Best,
Christoph

Task Complete Email

I figured I would open an issue to discuss possible solutions to the email notification. User privacy is important and it appears the available solutions could be pretty limited. So as far as privacy, we shouldn't be able to tell who and where an email is being sent correct?

Regression: Redirecting output fails

In pyprind 2.9.8 it was possible to redirect stdout to a file and still see the progress from pyprind.
Since 2.9.9, the progress doesn't show when redirecting stdout. Instead, a message is output to stdout:

Warning: No valid output stream.

I have only just upgraded to 2.10 directly from 2.9.8, so I hadn't noticed this before.

The problem can be seen by simply running the following as python pyprind_bug.py > output_file

from time import sleep
from pyprind import prog_bar

for i in prog_bar(range(5)):
    sleep(1)

Jupyter Notebook Output - ETA Repeated

Hi,

First off, thanks for the nice library. I typically use pyprind within a Notebook (IPython/Jupyter). After updating to the latest version of Jupyter Notebook, I get some repeated ETA messages.

Here's an example:

import pyprind
import time

for i in pyprind.prog_bar(range(50), stream=1):
    time.sleep(0.1)

And here's the output:

0%                          100%
[##############################] | ETA: 00:00:04 | ETA: 00:00:04 | ETA: 00:00:04 | ETA: 00:00:04 | ETA: 00:00:04 | ETA: 00:00:04 | ETA: 00:00:03 | ETA: 00:00:03 | ETA: 00:00:03 | ETA: 00:00:03 | ETA: 00:00:03 | ETA: 00:00:03 | ETA: 00:00:02 | ETA: 00:00:02 | ETA: 00:00:02 | ETA: 00:00:02 | ETA: 00:00:02 | ETA: 00:00:02 | ETA: 00:00:01 | ETA: 00:00:01 | ETA: 00:00:01 | ETA: 00:00:01 | ETA: 00:00:01 | ETA: 00:00:01 | ETA: 00:00:00 | ETA: 00:00:00 | ETA: 00:00:00 | ETA: 00:00:00 | ETA: 00:00:00 | ETA: 00:00:00 | ETA: 00:00:00
Total time elapsed: 00:00:05

pyprind==2.9.9, jupyter==1.0.0, notebook==4.4.1

I'm not too familiar with the inner workings of this library, so hopefully you can let me know if this might be an issue with pyprind, or if I should open an issue in the jupyter notebook project.

Thanks in advance,
Phil

pyprind with joblib

Is it possible to use the callback from joblib parallel to make it work with pyprind for Parallel processing tasks ?

Flushing the stdout

I have seen when I am printing some messages using print() statement prior to creating object of pyprind.ProgBar, the process bar gets split into separate parts like example below:

0%                          100%
Dataset: muct-subjects.txt   Task: genuine  VGG: orig/
Number of Subjects:  276
[##############################] | ETA: 00:00:00
Total time elapsed: 00:00:06

In order to fix this, I had to manually flush the stdout with:

import sys
sys.stdout.flush()

and that will fix it.

Just as a suggestion, it will be helpful to put the sys.stdout.flush() in the constructor to take care of it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.