When to evaluate a custom math function in a tikzpicture environment using pgfplots

I want to draw a custom function using pgfplots, and add an annotation node:

\begin{tikzpicture}[
>=stealth,
evaluate={
function f(\x) {
return cos(2*\x);
};
}
]
\begin{axis}[
axis lines=middle,
xtick=\empty,
ytick=\empty,
xmin=-200,
xmax=200,
ymin=-1.5,
ymax=1.5
]
domain=-180:180,
samples=361
]{f(x)};
% \node[coordinate,pin=above right:{$\cos 2x$}] at (axis cs:45,{f(45)}) {};
\node[coordinate,pin=above right:{$\cos 2x$}] at (axis cs:45,0) {};
\end{axis}
\end{tikzpicture}


The result is:

My question is about the commented line above, which cannot be compiled correctly. The reason, IMHO, is probably related to the function evaluation process (say, function f above). I am not quite understand the mechanism of it, so is there any way to solve this problem? An extra explanation is quite appreciated!

BTW: Instead of evaluate, I have also tried declare function, which works fine in this scenario; yet the actual custom function involves a complicated expression (defined in a recursive manner), which might not be handled by declare function.

Your commented code does work provided you load the math library.

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{math}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\begin{document}
\begin{tikzpicture}[
>=stealth,
evaluate={
function f(\x) {
return cos(2*\x);
};
}
]
\begin{axis}[
axis lines=middle,
xtick=\empty,
ytick=\empty,
xmin=-200,
xmax=200,
ymin=-1.5,
ymax=1.5
]
domain=-180:180,
samples=361
]{f(x)};
\node[coordinate,pin=above right:{$\cos 2x$}] at (axis cs:45,{f(45)}) {};
%\node[coordinate,pin=above right:{$\cos 2x$}] at (axis cs:45,0) {};
\end{axis}
\end{tikzpicture}
\end{document}


Note, however, that it might be nontrivial to marry math to the fpu library, which pgfplots uses in its plots, in full glory. That is, if you want to play with recursive functions that work with integers, you may need to locally switch off fpu.

As for the question in the comments: there is a problem with xelatex or lualatex running on a beamer document including this code and using the metropolis theme. A probably related problem is discussed here. Among other things, metropolis sets the version of pgfplots to the value 1.9. Here is a temporary workaround for that constellation. You need to choose a different variable for the function (which is of course just a placeholder, but this definitely should not be necessary). That is, use

evaluate={
function f(\t) {
return cos(2*\t);
};
}


where \x got replaced by \t. Full code:

\documentclass{beamer}
\usetheme{metropolis}
\usepackage{pgfplots}
\usetikzlibrary{math}
\begin{document}
\pgfplotsset{compat=1.17}

\begin{frame}[t,fragile]
\frametitle{}
\begin{tikzpicture}[
>=stealth,
evaluate={
function f(\t) {
return cos(2*\t);
};
}
]
\begin{axis}[
axis lines=middle,
xtick=\empty,
ytick=\empty,
xmin=-200,
xmax=200,
ymin=-1.5,
ymax=1.5
]
domain=-180:180,
samples=361
]{f(x)};
\node[coordinate,pin=above right:{$\cos 2x$}] at (axis cs:45,{f(45)}) {};
%\node[coordinate,pin=above right:{$\cos 2x$}] at (axis cs:45,0) {};
\end{axis}
\end{tikzpicture}
\end{frame}

\end{document}


• Thanks for your help! I just tried yours, it really works. The reason seems to be related to the metropolis beamer theme. When I use that theme, the error occurs. Maybe that is another story. Mar 31, 2020 at 8:24
• @oaheix Maybe there is yet another ingredient. When I wrap the above tikzpicture in \documentclass{beamer} \usetheme{metropolis} \usepackage{pgfplots} \usetikzlibrary{math} \pgfplotsset{compat=1.16} \begin{document} \begin{frame}[t] \frametitle{A plot} ... \end{frame} \end{document}, it also runs through on my updated TeXLive 2019 installation.
– user194703
Mar 31, 2020 at 13:11
• I tried it again using pdflatex, it works; yet it does not work using xelatex (which is used in my work) or lualatex. Apr 18, 2020 at 2:16
• @oaheix I tested this now explicitly on my updated TeXLive 2020 installation: here the above example works with pdflatex, lualatex and xelatex. However, the modified version with beamer and metropolis does not work with lualatex nor xelatex. It is also true that the metropolis theme has the suspicious ingredient \AtEndPreamble{% \@ifpackageloaded{pgfplots}{% \RequirePackage{pgfplotsthemetol} }{} } where pgfplotsthemetol does some weird things including compat=1.9. So seems like someone had to make some strange hard-coded choices for us.
– user194703
Apr 18, 2020 at 2:34
• @oaheix I added a workaround for that configuration. There seem to be issues with the interactions between metropolis and pgfplots.
– user194703
Apr 18, 2020 at 3:12