7

I'm trying to read two functions of x from a file, and then get the result of f(8) / g(8) using pgfmathparse.

Here is a minimal (not) working example:

\begin{filecontents}{data.dat}
f(x) g(x)
x    x+1
\end{filecontents}

\documentclass{article}
\usepackage{xstring,pgfplotstable,filecontents}

\begin{document}

\newcommand{\getfx}[1]{
  \pgfplotstablegetelem{#1}{f(x)}\of{data.dat}
}
\newcommand{\getgx}[1]{
  \pgfplotstablegetelem{#1}{g(x)}\of{data.dat}
}

\def\feight{
  \getfx{0}
  \StrSubstitute[0]{\pgfplotsretval}{x}{8}
}

\def\geight{
  \getgx{0}
  \StrSubstitute[0]{\pgfplotsretval}{x}{8}
}

\pgfmathparse{
  (\feight)/(\geight)
}
\pgfmathresult

\end{document}

Using this, I am able to print f(8)/g(8) easily (which is to say, "8/(8+1)"), but the pgfmathparse bit gives me an error on compilation "Undefined control sequence." on L30.

What can I do to fix this code?

  • Does that compile without error for you? Because it does not for me. However, I don't get the error you report. – cfr Jan 3 '16 at 2:09
  • I don't see how this can work when you are trying to treat the same thing as numerical data, a string and a maths expression.... But I don't know much about the package you're using, so maybe it has some clever tricks to manage this kind of thing. – cfr Jan 3 '16 at 2:58
  • Thank you so much for the comments @cfr. The given code won't compile for me. This is the full output when I try to compile the newly edited doc in the original post using pdflatex: sprunge.us/WdTX I think how this works is, everything is being treated as a string, but the special function \pgfmathparse is able to convert its input strings to math expressions and return the result as a string. So really the only representation I'm dealing with is strings. Also it's important to note that everything up until the maths works; I can do \geight and it'll display 8+1 for example. – Harry Jan 3 '16 at 3:25
  • Maybe it is just an expansion problem, then...? But trying to expand things just gets complaints about \pars. You certainly wouldn't normally put \frac{}{} inside \pgfmathparse like that. Either you want it to evaluate the fraction and you give it the fraction or you want it to evaluate the numerator and denominator separately and you need to parse each expression before printing the combined fraction. – cfr Jan 3 '16 at 3:30
  • @cfr: Looks like you're right about \frac, but even if I replace that with (\feight) / (\geight) I still get the same error so the question unfortunately still stands. I'll update the question now though. I would totally be willing to modify the structure of this document in any way so that the functions are applied and divided; is there a better way to do it? – Harry Jan 3 '16 at 3:56
2

Edit

You can do this without xstring if you have the input slightly modified. The previous code fails because pgfmath does not like \x{}. So I simply change it to (\x). (You cannot leave \x along because otherwise pgfplotstable will not see the space between \x and \x+1.)

\documentclass{article}
\usepackage{pgfplotstable,filecontents}

\begin{filecontents}{data.dat}
f(\x) g(\x) h(\x)
(\x) \x+1  f(\x)/g(\x)
\end{filecontents}

\begin{document}
{
\def\x{variable x}
\def\DeclareFunctionFromTable#1{
    \pgfplotstablegetelem{0}{#1}\of{data.dat}
    \expandafter\DeclareFunctionFromTableAux\expandafter{\pgfplotsretval}{#1}
}
\def\DeclareFunctionFromTableAux#1#2{\tikzset{declare function={#2=#1;}}}

\DeclareFunctionFromTable{f(\x)}
\DeclareFunctionFromTable{g(\x)}
\DeclareFunctionFromTable{h(\x)}

\begin{tikzpicture}
    \begin{axis}
        \addplot(\x,{f(\x)});
        \addplot(\x,{g(\x)});
        \addplot(\x,{h(\x)});
    \end{axis}
\end{tikzpicture}
\end{document}

You can do this without xstring if you have the input slightly modified.

\documentclass{article}
\usepackage{pgfplotstable,filecontents}

\begin{filecontents}{data.dat}
f(\x) g(\x) h(\x)
\x{}  \x+1  f(\x)/g(\x)
\end{filecontents}

\begin{document}

\def\x{x}
\def\DeclareFunctionFromTable#1{
    \pgfplotstablegetelem{0}{#1}\of{data.dat}
    \expandafter\DeclareFunctionFromTableAux\expandafter{\pgfplotsretval}{#1}
}
\def\DeclareFunctionFromTableAux#1#2{\pgfkeys{/pgf/declare function={#2=#1;}}}

\DeclareFunctionFromTable{f(\x)}
\DeclareFunctionFromTable{g(\x)}
\DeclareFunctionFromTable{h(\x)}

\pgfmathparse{h(8)}
\pgfmathresult

\end{document}

  • Thanks! I like this approach a lot, but if I try to apply any number greater than one character long (like h(10)) I get the same "! Undefined control sequence." error on L22? What can be done to fix this? – Harry Jan 3 '16 at 19:24
3

There is some expansion stuff going on (which I don't understand so won't attempt to explain it). But, here is one way to achieve the desired results:

enter image description here

Code:

\begin{filecontents}{data.dat}
f(x) g(x)
x    x+1
\end{filecontents}

\documentclass{article}
\usepackage{xstring,pgfplotstable,filecontents}

\begin{document}

\newcommand{\getfx}[1]{
  \pgfplotstablegetelem{#1}{f(x)}\of{data.dat}
}
\newcommand{\getgx}[1]{
  \pgfplotstablegetelem{#1}{g(x)}\of{data.dat}
}

\def\SetFeightValue{%
  \getfx{0}%
  \StrSubstitute[0]{\pgfplotsretval}{x}{8}[\feightValue]%
}

\def\SetGeightValue{%
  \getgx{0}%
  \StrSubstitute[0]{\pgfplotsretval}{x}{8}[\geightValue]%
}

\SetFeightValue
\SetGeightValue
\pgfmathsetmacro{\MyResults}{(\feightValue)/(\geightValue)}

(\feightValue)/(\geightValue)=\MyResults

\end{document}

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.