14/07/2011

Latex \psfragfig of figures in other folders

What I've spent part of today wrestling with...

I've detailed previously how I'm exporting Matlab plots and including them in Latex documents. This works very well for figure files in the same directory - which is kind of the way Latex is set up. Unfortunately I'd like to maintain my folder structure in a different manner, for example, I have a "results" folder and a "thesis" folder both at the same level. Within "results" I have my Matlab plotting scripts and the images that are automatically saved by them. In my "thesis" folder I have my Latex files, in which I would like to include my results images.

Ideally I would be able to simply reference the image in my Latex document but that's not quite how it worked out. Let me explain what I tried...

Using \graphicspath
This is the most obvious way of doing things as noted here, and it works fine for graphics inserted with the \includegraphics command. I was also able to reference relatively like this: \graphicspath{{../results/}} and apparently it would also look in all the subdirectories if I put a double slash on the end: \graphicspath{{../results//}}.

This would be a great solution if I were using the \includegraphics command - but I'm not. I'm using \psfragfig and it doesn't work with this command, I guess because it's not set up to?

There is also a suggestion here that this method shouldn't be used, in favour of adding the images directory within your Latex compiler setup - although I'm not sure this would be appropriate for what I was trying to do.

Using \input, \include or \import
These all do similar things, in that they allow you to bring in latex documents from elsewhere in a folder structure. Only some of them will allow relative linking via higher level directories (rather than just subdirectories). \import seemed to be what I needed (or rather the \subimport variant of it did), so I set up a .tex file containing only my \psfragfig command within the "results" folder and imported that into my document. This got the figure into the document, but it didn't do all the nice text replacement that it was supposed to. In this respect it was no better than the previous technique.

After some experimentation it seems that \psfragfig only looks locally to the master document for the .tex files that it uses to include text with the figures.

Using \write18
So it appeared that the only way I was going to get the \psfragfig command to work properly was by having both the "figure.eps" file and the "figure.tex" file local to the master document. I'm not keen on the unnecessary duplication involved in this, so at the very least I decided to make it automatic. I therefore set it up so that these two files are automatically copied to the local directory during compile. This means that I always have the most up to date version of them in my document, and everything stays nice and automatic.

I think the only way to copy a file around between directories from within a Latex document is by issuing a system level command using \write18. This is usually disabled by default in Latex as it has the possibility of really mucking things up in your system if you were compiling 3rd party code. Therefore I had to compile my code with the extra argument '--shell-escape' as detailed here.

So I want to use the Latex \write18 command to execute a DOS copy command, that's fine; but there is also the tricky issue of needing to use backslashes for the path in the DOS copy command - these are obviously reserved in Latex. Therefore I had to use the technique outlined here to get around this.

So finally I managed to put together a Latex command that works, and it looks like this:
\def\psfragfigremote{\begingroup\catcode 92 12 \execB}
\def\execB#1#2%
{\immediate
\write18{copy #1#2.eps}%
\write18{copy #1#2.tex}%
\psfragfig*{#2}
\endgroup
}

So after including that in my header I can reference figures in other directories in my document like so:
\psfragfigremote{..\results\}{figure}
This copies both figure.eps and figure.tex (generated from Matlab with the matlabfrag command) from the results folder into the current folder and then includes them in the document.

It works fairly well, but not the first time it is run. I'm not sure why this is, possibly it hasn't finished copying the .tex file before starting to execute the next command. Therefore two compiles may be necessary to get all the labels sorted out.

I'm sure there must be a better way of doing this, possibly modifying the \graphicspath and \psfragfig commands so that they play well together would be a neater solution, but this works ok for now.

I hope this is of use to someone. Any improvements or suggestions then please comment.

UPDATE: Replacing the \write18 commands with:
\write18{robocopy #1 . #2.tex #2.eps}%
and removing the star after \psfragfig will only copy the files if they have changed, speeding up processing significantly.

1 comment: