3

I got a question very similar to this post (\includegraphics{\input{|shell command}}) which unfortunately hasn't been really answered.

The aim is to make a command that invokes a python script to make a plot figure, which is then inserted in LaTeX. What I have tried so far is the following:

main.tex:

\newcommand\pytexplot[1]{
   \immediate\write18{python pytexplot.py #1}
   \input{shellout}
}

\begin{document}

\includegraphic{\pytexplot{plot1}}
\includegraphic{\pytexplot{plot2}}

\end{document}

pytexplot.py is a python script that makes different plots depending on the provided parameter and saves a file shellout.tex containing the name and location of the image of the generated plot.

The error thus reported is an undefined control sequence (100+ in total), so I'm afraid this won't help much..

So far I figured it has to do with macro expansions, and tried putting in \expandafter at different positions but to no avail.

EDIT: wipet's 2nd suggestion seems to work, but it includes the same plot twice. Also, I don't know how to combine it with the shell command

Could someone help me out on this?

  • Welcome to TeX.SX! Usually, we don't put a greeting or a “thank you” in our posts. While this might seem strange at first, it is not a sign of lack of politeness, but rather part of our trying to keep everything very concise. Accepting and upvoting answers is the preferred way here to say “thank you” to users who helped you. – darthbith Sep 27 '14 at 18:13
  • 1
    I think you just want input{shellout} assuming shellout.tex is the file congaing the desired plot. If that does not answer your question I'd suggest you compose a fully compilable MWE including \documentclass and the appropriate packages that sets up the problem. – Peter Grill Sep 27 '14 at 19:11
  • Side note: there is no \includegraphic, it is \includegraphics. A MWE starting with \documentclass would be better. – user4686 Sep 28 '14 at 10:07
2

If the file shellout.tex just contains one line with the file name of the generated file, then

\usepackage{catchfile}
\newcommand{\includeplot}[2][]{%
  \immediate\write18{python pytexplot.py #2}%
  \CatchFileDef\plotpath{shellout.tex}{\endlinechar=-1 }%
  \includegraphics[#1]{\plotpath}%
}

in the preamble, with

\includeplot{plot1}

in the document or

\includeplot[<options for \includegraphics>]{plot1}

should do what you need.

  • Thanks, this actually works for me! On top of that, I now define the folders in LaTeX and pass them as arguments to python, eliminating the need for python to pass its output to LaTeX again. – Dirk van den Bekerom Sep 28 '14 at 10:38
4

When you've got a shell command which creates plot1 in shellout.tex file, then you can simply modify this shell command in order it creates

\includegraphics{plot1}

instead simple plot1 in the shelloupt.tex file. And you can simply use

\input shellout

But if you insist on the idea that your shell command creates only plot1 in your shellout.tex file then the code is slightly more complicated:

{\everyeof={\noexpand}\xdef\filecontent{\csname @@input\endcsname shellout }}
\def\tmp#1 {\def\filecontent{#1}}\expandafter\tmp\filecontent
\expandafter\includegraphics\expandafter{\filecontent}

Edit: The question were edited, the reaction to this modification follows.

You can define

\def\pytexplot#1{%
   \immediate\write18{python pytexplot.py #1}%
   {\endlinechar=-1\everyeof={\noexpand}\xdef\filecontent{\csname @@input\endcsname shellout }}%
   \includegraphics\filecontents
}

and you can use only

\pytexplot{plot1}
\pytexplot{plot2}

If you explicitly needs to write \includegraphics{\pytexplot{...}} in your document then you have to redefine \includegraphics like \pytexplot above and \def\pytexplot#1{#1}. But if you are using the command \includegraphics to another needs then this is not so simple. You need to implement more intelligence to your \includegraphics redefinition.

Comments:

  1. The \tmp in my first code removes the space generated by \endlinechar. But setting \endlinechar=-1 locally (suggested by jfbu) seems to be better, so I use this in my second code.

  2. IMHO simplest solution is to generate the \includegraphics{out1}, \includegraphics{out2} by python and to define: \def\pytexplot#1{\immediate\write18{python pytexplot.py #1}\input shellout }

  • It seems to do what I requested alright, but it's still not working out completely for me. I will update the original question with a full MWE. In the mean time, could you perhaps explain what's going on step by step? I'm not sure how the \tmp command comes into play.. – Dirk van den Bekerom Sep 27 '14 at 21:17
  • @wipet with \endlinechar-1\relax perhaps you would not need the \tmp thing. – user4686 Sep 27 '14 at 21:20
  • I believe that \CatchFileDef\filecontent{shellout}{\endlinechar=-1 } will avoid many headaches (requires \usepackage{catchfile}). – egreg Sep 27 '14 at 23:55
  • The reason I don't want python to output the \includegraphics line is that I have a lot of plots, and I want to be able to control each of the included graphics by parameters in LaTeX. I think what would work for me is make a new macro, say, \includepytexplot that can take all the arguments that \includegraphics has. – Dirk van den Bekerom Sep 28 '14 at 9:05
1

[moved from a comment]

Just to provide additional context to already given answers:

You can not, in general, hope to pass to some LaTeX command expecting something like a filename, a macro as argument; at best (and not always) the command will be of the type which attempts to expand its argument, and as soon as this argument does unexpandable things, it is highly probable that the command will not function.

In the case of \includegraphics you can use it with \temp as argument if \temp expands to a legitimate file name. But if \temp needs to make definitions, or contains a \write operation, you are doomed (no matter how many \expandafter you try to fiddle with)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.