6

Any idea, why the following doesn't work and how to fix ist:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{pgfplots}


\begin{document}
\begin{tikzpicture}
\begin{axis}[no markers]
   \pgfmathsetmacro{\i}{0}
   \foreach \f in {sin(deg(x)),x^2}
   {
   \addplot  {\f} node [pos=0.6,right] {\i};
   \pgfmathsetmacro{\i}{\i+1};
   }
\end{axis}
\end{tikzpicture}

\end{document}

I get the following output:

output

Edit:

I want that the value of \i in my loop is the same for one pass of the loop regardless if I use \i for a node or something else (which may be related to expanding problems), at the end of the loop I want to set a new value of \i.

Or to say it in other words: I just want to use the variable \i as one would do it in other programming languages inside a loop...

student
  • 29,003
  • Do you just want to number the plots, or will you need a more elaborate math expression for \i in your real application? – Jake Sep 24 '12 at 17:45
  • No it's not about numbering the plots. Yes I also want to use a more elaborate math expression. However the aim of the question is more about just to understand why the iteration doesn't work and how I can fix it, its more about learning about how to "program" in LaTeX rather than solving a particular problem like numbering plots or something like that... – student Sep 24 '12 at 17:51
  • If I understand the problem (it would help if you explained what you wanted to happen), this is because the interior of the foreach is inside a group so the assignment of \i is reset each time around the loop. You could put \global\let\i=\i to make it have effect outside. If you want integers, use \pgfmathtruncatemacro instead of \pgfmathsetmacro. – Andrew Stacey Sep 24 '12 at 17:54
  • @AndrewStacey: That's only part of the problem. The resetting issue could be solved by using \pgfplotsforeachungrouped instead of \foreach, but another issue is that the node content is not expanded at the time of the definition, but only at the time of drawing (after the plot is finished), so all nodes would have the same value (the final value of \i). – Jake Sep 24 '12 at 17:58
  • Yes, the main problem is, that \i seems not to change it's value... – student Sep 24 '12 at 18:00

1 Answers1

10

There are two issues at play here:

  1. The assignment of \i is local to the group introduced by \foreach, so \i is reset for each iteration. You can solve this by replacing \foreach with \pgflotsforeachungrouped, which doesn't introduce grouping.
  2. The content of the node is not expanded, but saved as \i. Nodes (and other TikZ drawing commands) in an axis environment aren't drawn immediately, but only after the axis is complete (otherwise it wouldn't be clear where to place the node). So with the current code, you'd end up with two nodes reading 2.0 (the final value of \i after two iterations). PGFPlots stores the node commands in the way they were defined, so you have two nodes containting \i, which are executed at the end of the plot, when the value of \i is 2.0.

    To make the node use the value of \i at the time the \addplot command was called, you can replace \addplot ... with

    \edef\doplot{\noexpand\addplot  {\f} node [pos=0.6,right] {\i};}
    \doplot
    

    What this does is create a new macro called \doplot, which contains \addplot {<content of \f>} node [pos=0.6, right] {<content of \i>}, so the two macros \f and \i have been expanded (hence the name *e*def). The \addplot command shouldn't be expanded, so we're protecting it using \noexpand.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{pgfplots}


\begin{document}
\begin{tikzpicture}
\begin{axis}[no markers]
   \pgfmathsetmacro{\i}{0}
   \pgfplotsforeachungrouped \f in {sin(deg(x)),x^2}
   {
       \pgfmathsetmacro{\i}{\i+1};
       \edef\doplot{\noexpand\addplot  {\f} node [pos=0.6,right] {\i};}
       \doplot
   }
\end{axis}
\end{tikzpicture}

\end{document}
Jake
  • 232,450
  • 1
    Thanks, that does what I want! Could you explain the line with \edef in some more detail? – student Sep 24 '12 at 18:18
  • @student: I've edited my answer to provide a bit more of an explanation. – Jake Sep 24 '12 at 18:27
  • @student: Cool! Expansion issues are a bit confusing, so you might have to read up on \let, \def, \edef, \noexpand and \expandafter a bit. – Jake Sep 24 '12 at 18:35
  • @jake: Please which version of pgfplots have you used? I get a slightly different output. The numbers 1.0 and 2.0 are superimposed on each other. Also, why didn't you use count key? \foreach [count=\fc] \f in {sin(deg(x)),x^2}{\global\let\fc\fc\addplot {\f} node [pos=0.6,right] {\fc};}. – Ahmed Musa Sep 25 '12 at 21:37
  • @AhmedMusa: I'm using version 1.6. I think the feature for positioning nodes as part of the plot definitions only appeared in version 1.5. I didn't use \count because the OP said in their comment on their question that they didn't just want to number their plots, but that their real applications require more elaborate mathematical operations. – Jake Sep 26 '12 at 06:27