3

I want to pass a float variable from a pythontex calculation to latex such that the variable can be used in a pgfplots plot as in the following example. The example code shows two approaches that don't work. The syntax for passing should be as short and convenient as possible.

\documentclass{article}

\usepackage[gobble=auto]{pythontex}
\usepackage{pgfplots}

\begin{document}

\begin{pycode}
from numpy import * 
coeffA = 7
coeffB = sqrt(coeffA)  
# print(r'\def\coeffA{%s}' %coeffA)
# print(r'\def\coeffB{%s}' %coeffB)
\end{pycode}



\begin{tikzpicture}
  \begin{axis}[xlabel=$x$,ylabel=$y$]
    %\addplot gnuplot {\coeffA*x**2 + \coeffB*x}; % Results in undefined control sequence error
    \addplot gnuplot {\py{coeffA}*x**2 + \py{coeffB}*x}; %Results in an empty plot without errors
  \end{axis} 
\end{tikzpicture}


\end{document}
1

2 Answers 2

3

Following @G.Poore's comment you can use pysub (beginning from version v0.15) as follows:

\documentclass{article}

\usepackage[gobble=auto]{pythontex}
\usepackage{pgfplots}

\begin{document}

\begin{pycode}
from numpy import * 
coeffA = 7
coeffB = sqrt(coeffA)  
\end{pycode}   

\begin{pysub}
\begin{tikzpicture}
  \begin{axis}[xlabel=$x$,ylabel=$y$]
    \addplot gnuplot {!{coeffA}*x**2 + !{coeffB}*x}; 
  \end{axis} 
\end{tikzpicture}
\end{pysub}

\end{document}
3

I can see a few issues here:

  1. You can't use \py{} directly inside \addplot gnuplot because it isn't fully expandable, so gnuplot gets literally \py{coeffA} as its input and not the value of the coefficient.

  2. The idea of defining \coeffA and \coeffB macros is good, but when you put the definitions inside the pycode environment they don't work since pycode doesn't typeset its contents (it doesn't return anything to LaTeX).

  3. Even if you move the defs further, they won't appear in the document on the first run, so you'll have to do something about it. In the code below I just define them as some dummy values just to avoid the error report.

To make things easier to use, I've added some code which automatically iterates through all global numeric variables and creates corresponding LaTeX macros. Then their usage in the main document becomes as easy as \pyvar{varname}.

The code:

\documentclass{article}

\usepackage[gobble=auto]{pythontex}
\usepackage{pgfplots}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\pyvar#1{\csname pythonvar@#1\endcsname}
\begin{pycode}
from numbers import Number
def exposeNumericGlobals():
  res = r'\makeatletter '

  d = globals()
  for key in d.keys():
    val = d[key]
    if isinstance(val, Number):
      res = res + (r'\gdef\pythonvar@%s{%s} ' % (key, val))

  res = res + r'\makeatother'
  return res
\end{pycode}
\AtBeginDocument{\py{exposeNumericGlobals()}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{pycode}
from numpy import * 
coeffA = 7
coeffB = sqrt(coeffA)
\end{pycode}

\begin{document}

\begin{tikzpicture}
  \begin{axis}[xlabel=$x$,ylabel=$y$]
    \addplot gnuplot {\pyvar{coeffA}*x**2 + \pyvar{coeffB}*x};
  \end{axis} 
\end{tikzpicture}
\end{document}

The output:

enter image description here

2
  • Thanks. It works. But the solution is pretty complicated for such a principially simple task. In particular that you have to define for the first run befor begin{document}.
    – Julia
    Oct 19, 2017 at 7:53
  • You're right. It's a bit too complicated. So I've separated the complicated part into a non-changing section. Now you just define a numeric global variable and use \pyvar{var}. The variable definition has to be before \begin{document} though. Oct 19, 2017 at 18:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .