4

I've got a few macros that perform floating point lookups and calculations for me and I'm interested 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?

user202729
  • 7,143
user1476176
  • 1,225

1 Answers1

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.