4

I've got a few macros that perform floating point lookups and calculations for me and I'm interesting in plotting their results. They're the kind of calculation which requires if/else, so they can't be easily written as a simple math formula for \addplot. Thanks to a previous question (Using PGFPlots to plot macro result), I now know to use \pgfmathdeclarefunction, but after trying it I've found that addplot seems to prepend a "0Y" or "1Y" to values before passing them as function arguments. My external macros aren't prepared to handle this extra text, and I'm not sure why it's there.

In the course of testing things out, I've also found that calling a function defined with pgfmathdeclarefunction can also change the positioning of the graph...

\documentclass{article}

\usepackage{xparse}

\usepackage{pgfplots}
\pgfplotsset{compat=1.10}

\begin{document}

% Example of a macro which does math outside of pgf
    \ExplSyntaxOn
    \DeclareExpandableDocumentCommand \doubleMacro { m }%
     {%
      \fp_eval:n { #1*2 }%Math performed by a package other than pgfplots
     }%
    \ExplSyntaxOff  

%Demo: macro does work in regular text
\doubleMacro{1.1}.

% Defining custom pgf functions for plotting

    \pgfmathdeclarefunction{mathDoubleMacro}{1}{%
        \pgfmathparse{\doubleMacro{#1}} %Calls macro which performs math done by another package
    }

    \pgfmathdeclarefunction{mathDoublePgf}{1}{%
        \pgfmathparse{#1*2} %Uses pgf to do the same thing as an external macro could
    }

%Generic plot with function given directly to \addplot
\begin{center}
\begin{tikzpicture}
    \begin{axis}
        \addplot[domain=0:1] {2*x};
    \end{axis}
\end{tikzpicture}
\end{center}

%Plot using first macro: complains about 'Unknown fp word Y.'
\begin{center}
\begin{tikzpicture}
    \begin{axis}
        %\addplot[domain=0:1] {mathDoubleMacro(x)};%Commented out because it gives problems
    \end{axis}
\end{tikzpicture}
\end{center}

%Plot using second macro: works, but graph is displaced to the right of the expected position
\begin{center}
\begin{tikzpicture}
    \begin{axis}
        \addplot[domain=0:1] {mathDoublePgf(x)};
    \end{axis}
\end{tikzpicture}
\end{center}

\end{document}

If I define mathDoubleMacro as calling a non-existent macro, then the errors show which x-values which the addplot is trying to evaluate y at:

  • 0Y0.0e0
  • 1Y4.1666e-2
  • 1Y8.3332e-2
  • ...
  • 1Y9.9998401e-1

What are these nY's all about, and why does \addplot[domain=0:1] {mathDoublePgf(x)} give a graph with different positioning?

  • 2
    Why you are adopting the hard way? You can directly use \pgfmathdeclarefunction. Is there anything wrong with it? – user11232 Apr 13 '14 at 22:26
  • This is minimum working example. In my real code doubleMacro involves calculations performed by other packages, and has no pgf math equivalent – user1476176 Apr 15 '14 at 16:46
3

The first problem, the strange Y characters can be considered to be a defect in pgfplots. In fact, it is the result of "premature optimization": pgfplots uses this format internally to represent floating point numbers in a normalized form - and it does not convert it back to IEEE numbers. Thinking about it, I believe that it should produce correct numbers.

Anyway, the solution for now is to apply \pgfmathfloatvalueof{#1} to convert the number to a "normal" representation.

This leads immediately to the second problem, the spurious spaces. They come from the white spaces after your function evaluations, and they are present in both macro definitions: directly after \pgfmathparse{\doubleMacro{#1}} and after \pgfmathparse{#1*2} %. This is one of the strangenesses of TeX. Normally TikZ swallows such spurious characters - I do not know why it doesn't in this context. The solution is to remove the spurious spaces by adding % directly afterwards.

Taking both items together repairs yours figures.

\documentclass{article}

\usepackage{xparse}

\usepackage{pgfplots}
\pgfplotsset{compat=1.10}

\begin{document}

% Example of a macro which does math outside of pgf
    \ExplSyntaxOn
    \DeclareExpandableDocumentCommand \doubleMacro { m }%
     {%
      \fp_eval:n { #1*2 }%Math performed by a package other than pgfplots
     }%
    \ExplSyntaxOff  

%Demo: macro does work in regular text
\doubleMacro{1.1}.

% Defining custom pgf functions for plotting

    \pgfmathdeclarefunction{mathDoubleMacro}{1}{%
        \pgfmathparse{\doubleMacro{\pgfmathfloatvalueof{#1}}}%Calls macro which performs math done by another package
    }

    \pgfmathdeclarefunction{mathDoublePgf}{1}{%
        \pgfmathparse{#1*2}%Uses pgf to do the same thing as an external macro could
    }

    \centering

%Generic plot with function given directly to \addplot
\begin{tikzpicture}
    \begin{axis}
        \addplot[domain=0:1] {2*x};
    \end{axis}
\end{tikzpicture}

%Plot using first macro: complains about 'Unknown fp word Y.'
\begin{tikzpicture}
    \begin{axis}
        \addplot[domain=0:1] {mathDoubleMacro(x)};%Commented out because it gives problems
    \end{axis}
\end{tikzpicture}


%Plot using second macro: works, but graph is displaced to the right of the expected position
\begin{tikzpicture}
    \begin{axis}
        \addplot[domain=0:1] {mathDoublePgf(x)};
    \end{axis}
\end{tikzpicture}

\end{document}

enter image description here

Note that I replaced \begin{center}...\end{center} by one \centering - this leads to less vertical whitespace. I only wanted to get all on one page; this is unrelated to the question.

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.