-
Notifications
You must be signed in to change notification settings - Fork 103
matplotlib
This page describes ways to make PythonTeX work with matplotlib more conveniently.
Suppose you have the following code in your document:
x = linspace(0, pi)
plt.plot(x, sin(x), label='sin(x)')
plt.plot(x, cos(x), label='cos(x)')If you want to quickly view these plots in your document, you could call plt.legend() and plt.savefig('foo.pdf') and then write the LaTeX code to include a figure. To simplify this process the following helper functions may be useful. (Modify them to suit your needs!)
# Set the prefix used for figure labels
fig_label_prefix = 'fig'
# Track figure numbers to create unique auto-generated names
fig_count = 0
def savefig(name='', legend=False, fig=None):
'''
Save the current figure (or `fig`) to file using `plt.savefig()`.
If called with no arguments, automatically generate a unique filename.
Return the filename.
'''
# Get name (without extension) and extension
# Start with default extension
ext = 'pdf'
if not name:
global fig_count
# Need underscores or other delimiters between `input_*` variables
# to ensure uniqueness
name = 'auto_fig_{}_{}_{}-{}'.format(pytex.input_family, pytex.input_session, pytex.input_restart, fig_count)
fig_count += 1
else:
if len(name) > 4 and name[:-4] in ['.pdf', '.svg', '.png', '.jpg']:
name, ext = name.rsplit('.', 1)
# Get current figure if figure isn't specified
if not fig:
fig = gcf()
# Put a nice legend on top of the figure (you may need to adjust this!)
# Only create legend if axis has labels
if legend and len(fig.gca().get_legend_handles_labels()[0]) != 0:
for ax in fig.axes:
if ax.is_first_row():
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width, box.height*0.9])
leg = ax.legend(loc="upper center", bbox_to_anchor=(0.5, 1.04), ncol=3, bbox_transform=fig.transFigure, frameon=False)
fig.savefig(name + '.' + ext)
fig.clf()
return name
def latex_environment(name, content='', option=''):
'''
Simple helper function to write the `\begin...\end` LaTeX block.
'''
return '\\\\begin{%s}%s\n%s\n\\\\end{%s}' % (name, option, content, name)
def latex_figure(name=None, caption='', label='', width=0.8):
''''
Auto wrap `name` in a LaTeX figure environment.
Width is a fraction of `\textwidth`.
'''
if not name:
name = savefig()
content = '\\\\centering\n'
content += '\\\\includegraphics[width=%f\\\\textwidth]{%s}\n' % (width, name)
if not label:
label = name
if caption and not caption.rstrip().endswith('.'):
caption += '.'
# `\label` needs to be in `\caption` to avoid issues in some cases
content += "\\\\caption{%s\\\\label{%s:%s}}\n" % (caption, fig_label_prefix, label)
return latex_environment('figure', content, '[htp]')The above code block can be included in your document's preamble via
\begin{pythontexcustomcode}[begin]
...
\end{pythontexcustomcode}Or you may store it in a file and import it in the usual way. Say you have a src directory alongside your document and the above code is in a file python_preamble.py:
\begin{pythontexcustomcode}[begin]{pylab}
# Might want sys.path.insert(1, '../src/') in some cases
# But then it would probably be better to use virtualenv
sys.path.append('../src/')
from python_preamble import *
\end{pythontexcustomcode}The figure for the example considered at the beginning may now be created very simply:
\begin{pylabcode}
x = linspace(0, pi)
plt.plot(x, sin(x), label='sin(x)')
plt.plot(x, cos(x), label='cos(x)')
fig = latex_figure()
\end{pylabcode}
\pylab{fig}Of course, we could also just print the figure, using print(latex_figure()) at the end of the pylabcode environment or using \pylab{latex_figure()} after the end of the environment.
Matplotlib 1.2 has a new pgf backend. This may be useful when you want to create graphics that are compiled at the same time as the document (for better font integration, etc.).