3

I want to draw a pulse train on which I write some information like the corresponding angle, etc... But I think I've got a problem with the two variables foreach loop because I can't even compile since I added this line

\addplot[dirac] coordinates {(\temps,0.75)};

The entire code is :

\documentclass[tikz]{standalone}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[french]{babel}
\usepackage{pgfplots}

\pgfplotsset{
  dirac/.style={
    mark=triangle*, mark options={scale=2}, ycomb, scatter, blue,
    visualization depends on={y/abs(y)-1 \as \sign},
    scatter/@pre marker code/.code={\scope[rotate=90*\sign,yshift=-2pt]}
  }
}

\begin{document}
  \begin{tikzpicture}
  \tikzset{
    every pin/.style={fill=yellow!50!white,rectangle,rounded                corners=3pt,font=\scriptsize},
    small dot/.style={fill=black,circle,scale=0.2}
}

\begin{axis}[axis lines=middle,x=1,xmin=-25,xmax=375,y=100,ymin=0,ymax=1,
  title={Train d'impulsions à 40MHz},ylabel={Tx},xlabel={Temps/ns},
  every axis y label/.style={at={(ticklabel cs:1)},anchor=near ticklabel},
  every axis x label/.style={at={(ticklabel cs:1)},anchor=near ticklabel},
  ytickmin=2, xtickmax=350, axis y line=left
  ]

  \foreach \temps/\angle in {0/-21, 25/-18, 50/-15, 75/-12}{
     \edef\temp{\noexpand
     \addplot[dirac] coordinates {(\temps,0.75)};
     \node[small dot,pin={$\angle\degres$}]  at (25+\temps,70) {};}
     \temp
  }

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

Thanks in advance for helping me. For my defense, I am a beginner in Tikz-PGF

  • I don't think that it is the addition of the plot which is the problem. That seems to work fine. It is the use of \temps in the coordinate specification of the additional node for the pin which seems to cause the issue. I can't get \temps recognised within \begin{axis}...\end{axis} at all... – cfr Aug 19 '14 at 23:21
  • Yes you're right. Even without the addplot line, it does not work at all. I get the following error message : "Undefined control sequence. }" – rhum187 Aug 20 '14 at 7:21
  • What I don't understand is that \temps seems to work fine in the \addplot line itself but even if I just try \node {\temps}, it won't work. I don't really use plots much, though, so probably I'm just not understanding how the axis environment works.... – cfr Aug 20 '14 at 15:51
2

Since the axis environment is postponing evaluation of some things until \end{axis}, the variables \temps and \angle don't exist anymore by then. In that case, you can use \pgfplotsinvokeforeach that immediately substitutes the loop counter for any #1 given in the loop body. The only drawback is that it doesn't support multiple loop variables, so you have to calculate one from the other like this:

\pgfplotsinvokeforeach{0,25,...,75}{
  \addplot[dirac] coordinates {(#1,0.75)};
  \node[small dot,pin={
    \pgfmathtruncatemacro{\angle}{#1/25*3-21}%
    $\angle\degres$
  }]  at (25+#1,70) {};
}

This yields:

Result

One additional hint: you should probably look at section 4.17 "Custom Annotations" of the pgfplots manual to see how you can specify node coordinates in the plot coordinate system using axis cs.


Technical details

It seems you tried to force the expansion of \temps and \angle using \edef, but doing so you have to protect anything you don't want expanded with \noexpand, which is quite tedious. If you move the creation of the pins out of the axis environment it works, but then it's difficult to line up the pins with the plot...

Besides that, \temps seems to be a bad choice for a macro name, although I can't say why. If you remove the \node from the loop, it still doesn't work:

\foreach \temps/\angle in {0/-21, 25/-18, 50/-15, 75/-12}{
   \addplot[dirac] coordinates {(\temps,0.75)};
}

fails with Incomplete \iffalse; all text was ignored after line <N>, for reasons unknown to me. If you rename \temps to \temp however, it works!

But that still doesn't allow you to use the \node command with \temp inside the loop. It still complains that \temp is undefined, because the \node macro is only evaluated at the end of the axis environment. One workaround is to manually force the expansion of \temp and \angle using \expandafter like this:

\def\LoopBody#1#2{%
  \addplot[dirac] coordinates {(#1,0.75)};
  \node[small dot,pin={$#2\degres$}]  at (25+#1,70) {};
}
\let\EA=\expandafter% For shorter code
\foreach \temp/\angle in {0/-21, 25/-18, 50/-15, 75/-12}{
   \EA\EA\EA\LoopBody\EA\EA\EA{\EA\temp\EA}\EA{\angle}
}

This expands first \angle to -21, then \temp to 0 and then \LoopBody{0}{-21} (etc). However that is not something I can really recommend because it's difficult to understand and debug. Maybe someone with a better understanding of the pgfplots internals can give some more insight as to why this is even necessary.

  • 1
    Thanks a lot for taking time to answer ! It works well with the '\pgfplotsinvokeforeach' command. – rhum187 Aug 21 '14 at 8:17
  • Oh, I didn't know about that command. Since you accepted my answer, I'll add info about \pgfplotsinvokeforeach. It doesn't support two loop variables though, does it? – Fritz Aug 21 '14 at 11:37
  • It doesn't support two loop variables I think. – rhum187 Aug 21 '14 at 12:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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