Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

This question already has an answer here:

I was trying to post a solution to How can I draw 25 horizontal lines instead of these 25 marked samples?, but I got stuck with a \foreach loop which wasn't behaving as I expected it to.

Here's my first attempt:

\documentclass[a4paper]{scrartcl}

\usepackage{tikz,pgfplots,amsmath}
\usepackage[T1]{fontenc}
\usepackage{lmodern,textcomp,siunitx}

\begin{document}

\begin{center}
\begin{tikzpicture}[font=\small]
\begin{axis}
  [
    height=5cm,
    width=6cm,
    scale only axis=true,
    %
    xlabel={\(\alpha\) in \si{\degree}},
    ylabel={\(\sin{(\alpha)}\)},
    %
    xtick=\empty, 
    ytick=\empty, 
    xticklabels={,,}, 
    yticklabels={,,}, 
    xmajorgrids={false}, 
    ymajorgrids={false}
  ]
  \addplot+[domain=0:360, 
            samples=25, 
            only marks, 
            mark=-] 
           {sin(x)};
  \foreach \myn in {1,...,25}
    {
      \pgfmathsetmacro{\myx}{360/(25-1) * (\myn-1)}
      \pgfmathsetmacro{\myy}{sin(\myx)}
      \draw (axis cs:0,\myy) -- (axis cs:360,\myy);
    }
\end{axis}
\end{tikzpicture}
\end{center}

\end{document}

I get an error:

! Undefined control sequence.
<argument> axis cs:0,\myy 

l.41 \end{axis}

? 

I wasn't expecting such an error. Nevertheless, I came up with a clunky work around. Here's my 2nd attempt which works quite well (though a bit clunky):

\documentclass[a4paper]{scrartcl}

\usepackage{tikz,pgfplots,amsmath}
\usepackage[T1]{fontenc}
\usepackage{lmodern,textcomp,siunitx}

\makeatletter
\def\aedrawline#1{%%
  \edef\mycontent{#1}
  \expandafter\ae@drawline\mycontent\@nil}
\def\ae@drawline#1,#2,#3\@nil{%%
  \draw (axis cs:#1,#3) -- (axis cs:#2,#3);
  }
\makeatother

\begin{document}

\begin{center}
\begin{tikzpicture}[font=\small]
\begin{axis}
  [
    height=5cm,
    width=6cm,
    scale only axis=true,
    %
    xlabel={\(\alpha\) in \si{\degree}},
    ylabel={\(\sin{(\alpha)}\)},
    %
    xtick=\empty, 
    ytick=\empty, 
    xticklabels={,,}, 
    yticklabels={,,}, 
    xmajorgrids={false}, 
    ymajorgrids={false}
  ]
  \addplot+[domain=0:360, 
            samples=25, 
            only marks, 
            mark=-] 
           {sin(x)};
  \foreach \myn in {1,...,25}
    {
      \pgfmathsetmacro{\myx}{360/(25-1) * (\myn-1)}
      \pgfmathsetmacro{\myy}{sin(\myx)}
      \aedrawline{0,
                  360,
                  \myy}
    }
\end{axis}
\end{tikzpicture}
\end{center}

\end{document}

All's good until @Tarass posts an answer which is very similar in concept to mine but avoids the clunky work around of my attempts:

\documentclass[a4paper]{scrartcl}

\usepackage{tikz,pgfplots,amsmath}
\usepackage[T1]{fontenc}
\usepackage{lmodern,textcomp,siunitx}

\begin{document}

\begin{center}
\begin{tikzpicture}[font=\small]
\begin{axis}
  [
    height=5cm,
    width=6cm,
    scale only axis=true,
    %
    xlabel={\(\alpha\) in \si{\degree}},
    ylabel={\(\sin{(\alpha)}\)},
    %
    xtick=\empty, 
    ytick=\empty, 
    xticklabels={,,}, 
    yticklabels={,,}, 
    xmajorgrids={false}, 
    ymajorgrids={false},
    after end axis/.code={%%
      \foreach \myn in {1,...,25}
        {
          \pgfmathsetmacro{\myx}{360/(25-1) * (\myn-1)}
          \pgfmathsetmacro{\myy}{sin(\myx)}
          \draw (axis cs:0,\myy) -- (axis cs:360,\myy);
        }
    }
  ]
  \addplot+[domain=0:360, 
            samples=25, 
            only marks, 
            mark=-] 
           {sin(x)};
\end{axis}
\end{tikzpicture}
\end{center}

\end{document}

Could someone explain what's going on here? In particular, why it that when the \foreach loop is called within the axis environment it is forgetful and needs instead to be processed from after end axis?

share|improve this question

marked as duplicate by A.Ellett, dustin, egreg, Adam Liter, cmhughes Apr 27 at 16:40

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

    
Have you seen percusse answer on my post here? It may be of some use. –  dustin Apr 27 at 16:01
    
@dustin Thank you for the link. I think that means my question should be closed as duplicate. –  A.Ellett Apr 27 at 16:14
    
I thought about that but wanted to see if that helped first before I did. –  dustin Apr 27 at 16:14
    
@dustin Except that it doesn't explain why Tarass's approach worked. –  A.Ellett Apr 27 at 16:16
1  
I may be wrong but it looks like it works since there is only one looped value sin(\i). In your code, you have \myy and \myx so you have to expand. You could probably use \pgfplotsinvokeforeach with Tarass. –  dustin Apr 27 at 16:19

1 Answer 1

up vote 3 down vote accepted

I guess that the problem is that TikZ/PGF doesn't like

\draw (axis cs:0,\myy) -- (axis cs:360,\myy);

because it wants to see “explicit” coordinates. Using the usual trick for expanding things it seems to work:

  \foreach \myn in {1,...,25}
    {
     \pgfmathsetmacro{\myx}{360/(25-1) * (\myn-1)}
     \pgfmathsetmacro{\myy}{sin(\myx)}         
     \begingroup\edef\x{\endgroup
       \noexpand\draw (axis cs:0,\myy) -- (axis cs:360,\myy);}%
     \x
    }

enter image description here

Why the difference with Tarass's code? I can't explain.

share|improve this answer
    
Why the \begingroup ... \endgroup? It seems to work fine without it. Since it's only a local definition within a \forloop it shouldn't be overwriting anything outside of the loop. Or am I missing something? –  A.Ellett Apr 27 at 16:11
    
@A.Ellett This way what \x is defined to be (if it's defined) is unimportant and its (re)definition will disappear as soon as it's expanded. –  egreg Apr 27 at 16:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.