# PGF math broken in \foreach loop

Following my previous question I've tried to make my example a bit more general as well as complex. (Note: I don't want this more complex, but this is what I want my graphics to do.)

When I have the following, I get the error:

NOTE: coordinate (2Y1.2575e-1],3Y0.0e0]) has been dropped because it is unbounded (in y). (see also unbounded coords=jump).
NOTE: coordinate (2Y7.55e-2],3Y0.0e0]) has been dropped because it is unbounded (in y). (see also unbounded coords=jump).
NOTE: coordinate (2Y2.525e-2],3Y0.0e0]) has been dropped because it is unboundd (in y). (see also unbounded coords=jump).
! Undefined control sequence.
<argument> \Xmid
, XS{\Xmid }
l.38     \end{axis}

?


The offending part is a \foreach statement; If I comment out the \foreach as shown below, everything compiles fine. Unfortunately, I need the \foreach statement to complete my graphics.

\documentclass{beamer}
\usepackage{tikz}
\usepackage{pgfplots}

\begin{document}

\begin{frame}[fragile]{Frame title}
\tikzset{declare function={XS(\x)=1/sqrt(\x);}}
\begin{tikzpicture}
\begin{axis}[
ticks = none,
axis x line = bottom,
axis y line = left,
xmin = -0.5,
ymin = 0.0,
ymax = 5.0,
]

\xdef\Xmin{0.1}
\xdef\Xmax{4.0}

\pgfmathsetmacro\startIndex{3}
% \foreach \n in {0,...,4}{
%   \pgfmathsetmacro{\onlyIndex}{int(\n+\startIndex)}
\pgfmathsetmacro{\Xmid}{(\Xmax-\Xmin)/2}

% \only<\onlyIndex->{
\only<3->{
\addplot[only marks, color=black, fill=white, samples at={\Xmid}]{XS(x)};
\draw[thick, dashed, color=red] (\Xmid, XS{\Xmid}) -- (\Xmax, XS{\Xmax});
}

\xdef\Xmax{\Xmid}
% }

\end{axis}
\end{tikzpicture}
\end{frame}
\end{document}


What is wrong with my \foreach loop that causes problems with \Xmid?

I'm trying to add points on the curve between the two left-most points and draw a line between them. I'm trying to create an animation illustrating how to create a linear approximation to a curve. The two left-most points changes (of course) at each iteration. This is a continuation of my previous question.

• Could it just be the usual \pgfmathtruncatemacro vs. \pgfmathsetmacro thingy? – user121799 Apr 25 '18 at 20:15
• @marmot I wasn't aware of \pgftruncatemacro, but I tried it where in both places and it does't fix it. – jlconlin Apr 25 '18 at 20:21
• @marmot No, he has int(..) which does the same thing. – Torbjørn T. Apr 25 '18 at 20:22
• \startIndex{3} is not used because when it is used (to set \onlyIndex), then things stop working. – jlconlin Apr 25 '18 at 20:25
• foreach inside the axis is scoped and does not survive until pgfplots gather everything. So instead you need to use \pgfplotsinvokeforeach{1,...,4}{...} and instead of \n use #1. – percusse Apr 25 '18 at 22:42

There were a few issues.

1. Better restrict the plot to a domain to switch off the warnings.

2. Use {XS(\Xmid)} instead of XS{\Xmid}. XS is a function that you have declared, and the correct syntax for evaluating a function uses ordinary brackets. The curly brackets around the result make TikZ evaluate the thing.

3. If you want an integer index, use \pgfmathtruncatemacro. (This was not really an issue here.)

4. I added \xdef\Xmid{\Xmid} before the loop such that it is global and known inside the loop.

I also added a mark at \Xmax.

\documentclass{beamer}
\usepackage{tikz}
\usepackage{pgfplots}

\begin{document}

\begin{frame}[fragile]{Frame title}
\tikzset{declare function={XS(\x)=1/sqrt(\x);}}
\begin{tikzpicture}
\begin{axis}[
ticks = none,
axis x line = bottom,
axis y line = left,
xmin = -0.5,
ymin = 0.0,
ymax = 5.0,
]

\xdef\Xmin{0.04}
\xdef\Xmax{4.0}

\pgfmathtruncatemacro\startIndex{3}
\only<\startIndex->{
\addplot[only marks, color=black, fill=white, samples at={\Xmax},
domain={1/25}:5,clip=false]{XS(x)};
}
\foreach \n in {0,...,6}{
\pgfmathtruncatemacro{\onlyIndex}{int(\n+\startIndex)}
\pgfmathsetmacro{\Xmid}{\Xmin+(\Xmax-\Xmin)/2}
\xdef\Xmid{\Xmid}
\only<\onlyIndex->{
\addplot[only marks, color=black, fill=white, samples at={\Xmid},
domain={1/25}:5,clip=false]{XS(x)};
}
\xdef\Xmax{\Xmid}
}

\end{axis}
\end{tikzpicture}
\end{frame}
\end{document}


• The loop was the whole point of the question, so odd thing to not care about. I see it works now though, so +1. – Torbjørn T. Apr 25 '18 at 20:31
• Okay so adding the \typeout{\onlyIndex,\Xmid} \xdef\Xmid{\Xmid} did the trick. What does it do and why is it needed? – jlconlin Apr 25 '18 at 20:33
• I've restricted my domain by added xmax=10.0, but that didn't change any of the warnings. I suspect you mean to restrict it in some other manner that I'm not aware of. – jlconlin Apr 25 '18 at 20:34
• @jlconlin I'll remove the \typeout, this was only for me to understand what's going on, and I left it by mistake. The issues were what I mentioned above + the thing I mentioned in my reply to Torbjørn. And no, xmax does not restrict the lower end of the interval, which is where the warnings come from. If you tell me what you want to achieve, I could try to rewrite my answer in such a way that that works. – user121799 Apr 25 '18 at 20:36
• @jlconlin I have rewritten my answer to include this and want to say sorry for my statement about \Xmax. I think now to understand its purpose. (However, I think that the new coordinate should be \Xmin+(\Xmax-\Xmin)/2 instead of (\Xmax-\Xmin)/2 since otherwise the coordinates become smaller than \Xmin. I also adjusted the range and xmin in such a way that the plot really reaches the maximal value ymax=5. – user121799 Apr 25 '18 at 21:01