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.

I am attempting to create plot labels whose positions are determined by a function. The root problem is that the labels do not stay where they are placed, but all of the them move to the position of the label last placed.

\documentclass[11pt]{article}
\usepackage{pgfplots}
\usetikzlibrary{calc}

\begin{document}
\def\MyFunction(#1, #2){(#1/1000)^2 * (#2/1000)^2 * 175}

\begin{figure}
\centering
\begin{tikzpicture}
    \begin{axis}
    [
     width=12cm, grid=major,
     ymin=0, ymax=30,
     xmin=0, xmax=1000, domain=0:1000, samples=100
    ]
    \edef\L{450}
    \addplot [solid] {\MyFunction(\L, x)};

    \pgfmathparse{\MyFunction(\L, 500)}
    \edef\tmp{\pgfmathresult}
    \node[anchor=south west, fill=white, fill opacity=0.5] (pt450) at ($(axis cs:500,\tmp)+(0.5cm,-0.5cm)$) {\L 1st};
    \draw[->](pt450.south east)--(pt450.south west)--(axis cs:500,\tmp);

    \edef\L{620}
    \addplot [solid] {\MyFunction(\L, x)};
    \pgfmathparse{\MyFunction(\L, 500)}
    \edef\tmp{\pgfmathresult}
    \node[anchor=south west, fill=white, fill opacity=0.5] (pf620) at ($(axis cs:500,\tmp)+(0.5cm,-0.5cm)$) {\L 2nd};
    \draw[->](pf620.south east)--(pf620.south west)--(axis cs:500,\tmp);
    \end{axis}
\end{tikzpicture}
\end{figure}
\end{document}

My end goal is to use \foreach to have several plots (with labels) generated without the redundancy of code, which is why I am not using different variable names for the second instance. Yes, I will be generating dynamic node names, but removed that here for simplicity.

I'm also open to alternate methods of placing the labels, because this method does seem more complex than it might have to be.

share|improve this question
    
Welcome to TeX.sx! –  Kurt Dec 3 '12 at 18:38
    
This will most likely require the use of \pgfplotsinvokeforeach or \pgfplotsforeachungrouped. The details depend a bit on your requirements: Do the labels need to be positioned on a case by case basis, as in your example? Then you'll probably need to go with \pgfplotsforeachungrouped and an \edef. Could you elaborate a bit on what you're aiming to do? –  Jake Dec 3 '12 at 19:32
    
The labels to need to move with the plot, but the only thing I will wish to change each loop iteration is '\L'. It seems like it's an issue with when the variables ('\L' and '\tmp') are expanded (correct latex term?), because right now it appears that the values in the second plot travel back and over writes the first. I know there is an '\expandafter' command, but is there an evaluate now command? –  Stephen Schneider Dec 3 '12 at 20:43
add comment

1 Answer

up vote 4 down vote accepted

As you said, this problem has to do with expansion issues: PGFPlots delays the actual placement of many objects to a later point (until after the axis limits are definite), and saves the things it needs to place in an unexpanded state. So when your nodes are actually drawn, the macro \L just contains the last value. To work around this, you could use the standard approach of defining a temporary macro in which you expand all the macros whose values you need. In your case, you could use something like this:

\edef\dostuff{%
    \noexpand\node[anchor=south west, fill=white, fill opacity=0.5] (pt450) at ($(axis cs:500,\tmp)+(0.5cm,-0.5cm)$) {\L 1st};
    \noexpand\draw[->](pt450.south east)--(pt450.south west)--(axis cs:500,\tmp);
}\dostuff

However, PGFPlots also provides its own looping command which takes care of expanding the contents of the loop. It's called \pgfplotsinvokeforeach{<list>}{...<code using #1 for the current list element>...}. Using this and the ability of PGFPlots to place nodes along a plot by adding node ... to your \addplot command, your can get this

using the following code

\documentclass[11pt]{article}
\usepackage{pgfplots}
\usetikzlibrary{calc}

\begin{document}
\def\MyFunction(#1, #2){(#1/1000)^2 * (#2/1000)^2 * 175}
\tikzset{
    label node/.style={
        anchor=south west,
        xshift=1em, yshift=-2ex,
        inner sep=2pt,
        pos=0.5,
        name=labelnode,
        append after command={
            (labelnode.south east) -- (labelnode.south west) -- +(-0.8em,1.6ex)}
    }
}


\begin{figure}
\centering
\begin{tikzpicture}
    \begin{axis}
    [
     width=12cm, grid=major,
     ymin=0, ymax=30,
     xmin=0, xmax=1000, domain=0:1000, samples=100
    ]
    \pgfplotsinvokeforeach{420, 620}{
        \addplot [solid] {\MyFunction(#1, x)} node [label node] {#1};
    }
    \end{axis}
\end{tikzpicture}
\end{figure}
\end{document}
share|improve this answer
    
Thanks! ....but, I copied the example exactly, and all of the labels appear almost out of sight below the left hand side of the x axis. I found in the 'pos' section in the pgf manual (p.191 v2.1): For all other path construction operations, the position placement does not work, currently. This will hopefully change in the future (especially for the arc operation) Is 2.1 not the current pgf release? Also good call with the 'inner sep' I had been looking for that option. –  Stephen Schneider Dec 4 '12 at 13:56
    
@StephenSchneider: The pos feature in the context of \addplot is provided by PGFPlots, not TikZ/PGF. You need a fairly recent version of PGFPlots (at least 1.5, I think) to use it. –  Jake Dec 4 '12 at 14:15
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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