"""A special directive for including a matplotlib plot. Given a path to a .py file, it includes the source code inline, then: - On HTML, will include a .png with a link to a high-res .png. - On LaTeX, will include a .pdf This directive supports all of the options of the `image` directive, except for `target` (since plot will add its own target). Additionally, if the :include-source: option is provided, the literal source will be included inline, as well as a link to the source. """ import sys, os, glob, shutil from docutils.parsers.rst import directives try: # docutils 0.4 from docutils.parsers.rst.directives.images import align except ImportError: # docutils 0.5 from docutils.parsers.rst.directives.images import Image align = Image.align import matplotlib import IPython.Shell matplotlib.use('Agg') import matplotlib.pyplot as plt mplshell = IPython.Shell.MatplotlibShell('mpl') options = {'alt': directives.unchanged, 'height': directives.length_or_unitless, 'width': directives.length_or_percentage_or_unitless, 'scale': directives.nonnegative_int, 'align': align, 'class': directives.class_option, 'include-source': directives.flag } template = """ .. htmlonly:: [`source code <../%(srcdir)s/%(basename)s.py>`__, `png <../%(srcdir)s/%(basename)s.hires.png>`__, `pdf <../%(srcdir)s/%(basename)s.pdf>`__] .. image:: ../%(srcdir)s/%(basename)s.png %(options)s .. latexonly:: .. image:: ../%(srcdir)s/%(basename)s.pdf %(options)s """ def makefig(fullpath, outdir): """ run a pyplot script and save the low and high res PNGs and a PDF in _static """ fullpath = str(fullpath) # todo, why is unicode breaking this formats = [('png', 100), ('hires.png', 200), ('pdf', 72), ] basedir, fname = os.path.split(fullpath) basename, ext = os.path.splitext(fname) all_exists = True if basedir != outdir: shutil.copyfile(fullpath, os.path.join(outdir, fname)) for format, dpi in formats: outname = os.path.join(outdir, '%s.%s' % (basename, format)) if not os.path.exists(outname): all_exists = False break if all_exists: print ' already have %s'%fullpath return print ' building %s'%fullpath plt.close('all') # we need to clear between runs matplotlib.rcdefaults() mplshell.magic_run(fullpath) for format, dpi in formats: outname = os.path.join(outdir, '%s.%s' % (basename, format)) if os.path.exists(outname): continue plt.savefig(outname, dpi=dpi) def run(arguments, options, state_machine, lineno): reference = directives.uri(arguments[0]) basedir, fname = os.path.split(reference) basename, ext = os.path.splitext(fname) # todo - should we be using the _static dir for the outdir, I am # not sure we want to corrupt that dir with autogenerated files # since it also has permanent files in it which makes it difficult # to clean (save an rm -rf followed by and svn up) srcdir = 'pyplots' makefig(os.path.join(srcdir, reference), srcdir) # todo: it is not great design to assume the makefile is putting # the figs into the right place, so we may want to do that here instead. if options.has_key('include-source'): lines = ['.. literalinclude:: ../pyplots/%(reference)s' % locals()] del options['include-source'] else: lines = [] options = [' :%s: %s' % (key, val) for key, val in options.items()] options = "\n".join(options) lines.extend((template % locals()).split('\n')) state_machine.insert_input( lines, state_machine.input_lines.source(0)) return [] try: from docutils.parsers.rst import Directive except ImportError: from docutils.parsers.rst.directives import _directives def plot_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): return run(arguments, options, state_machine, lineno) plot_directive.__doc__ = __doc__ plot_directive.arguments = (1, 0, 1) plot_directive.options = options _directives['plot'] = plot_directive else: class plot_directive(Directive): required_arguments = 1 optional_arguments = 0 final_argument_whitespace = True option_spec = options def run(self): return run(self.arguments, self.options, self.state_machine, self.lineno) plot_directive.__doc__ = __doc__ directives.register_directive('plot', plot_directive)