##// END OF EJS Templates
Merge with upstream/
Merge with upstream/

File last commit:

r1694:d7a600ad
r1731:adf0e9f0 merge
Show More
plot_directive.py
155 lines | 4.6 KiB | text/x-python | PythonLexer
"""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)