[Tex/LaTex] Matplotlib PGF images in subdirectory

importmatplotlibtikz-pgf

I have a two-dimensional image plotted by Matplotlib using the PGF backend. It is stored in the figures subdirectory (since I have a lot of images and don't want to clutter up the main folder). As an example of the generation process:

from matplotlib import pyplot as plt
import numpy as np

plt.imshow(np.random.randn(200, 200))
plt.title('Some random data')
plt.savefig('figures/test.pgf')

The figures subdirectory now contains test.pgf and the raster image test-img0.png. The PGF file includes the command \pgfimage[interpolate=true,width=4.810000in,height=4.810000in]{test-img0.png}} to include the PNG. Since it (by design) does not contain the figures/ prefix, I need to find a workaround. According to a comment at a top of the PGF file (and backed up by this comment on the Matplotlib issue tracker) I can use the import package to make things work:

\documentclass{article}

\usepackage[margin=2cm]{geometry}
\usepackage{import}
\usepackage{pgf}

\begin{document}

\begin{figure}
\begin{center}
\import{figures/}{test.pgf}
\end{center}
\end{figure}

\end{document}

When I compile this (xelatex test), I get the message

Package pgf Warning: File "test-img0.png" not found when defining image "pgflastimage".
(pgf) Tried all extensions in ".pdf:.jpg:.jpeg:.png:" on input line 62.

The PGF file is found, so the resulting PDF has the axes, title etc, but just a placeholder instead of the PNG.

I also tried defining \graphicspath{{figures/}} but PGF doesn't seem to use that either.

Adding the figures directory to the TEXINPUTS environment variable prior to compiling works, but it isn't the cleanest workaround. I could also edit the PGF file to include the path, but I'd have to do that every time I regenerate the image. Can anybody suggest why import isn't working, or an alternative method?

Best Answer

Quick answer

Since the command that imports the png files inside the pgf image is pgfimage, I redefined it like this:

\let\pgfimageWithoutPath\pgfimage 
\renewcommand{\pgfimage}[2][]{\pgfimageWithoutPath[#1]{figures/#2}}

The first line copies the original pgfimage command to a temporary pgfimageWithoutPath. The second line redefines pgfimage to be the same as pgfimage, but prefixing the path with figures/.

Read below for more details

I actually use the chapterfolder package, which allows me to split the document into subfolders, one per chapter. It's very cool for long documents but needs a workaround for importing the figures, exactly the same problem that you had. So in the end my importing for pgfs works like this:

  1. This is the same as above, but using chapterfolders' directives.

    \let\pgfimageWithoutCF\pgfimage
    \renewcommand{\pgfimage}[2][]{\pgfimageWithoutCF[#1]{\cfcurrentfolder\subfigurepath#2}}
    
  2. This is a wrapper to \input{figure.pgf}, which includes the chapter path:

    \newcommand{\includepgf}[1]{\input{\cfcurrentfolder\subfigurepath#1.pgf}}
    
  3. And finally this is a shortcut to make the figure fit exactly the width of the text (to be used like

    % usage: \resizepgf[<optional size (defaults to textwidth)>]{<filename>}
    \newcommand{\resizepgf}[2][\textwidth]{
        \resizebox{#1}{!}{\includepgf{#2}}
    }
    

Thanks to jevopi's little blog for the how-to.

Related Question