9

I'd like to add annotations outside the plotting area, at the right axis, and at positions that depend on the coordinates of the plot.

I could do that with custom ticks, or adding nodes manually, but in the latter case I have to give the code in after end axis or disable clipping (which can have other undesirable effects, such as... not clipping). The best solution I've found so far is this:

\documentclass{article}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}

\def\angs{0.529177208354}
\def\ev{27.2113838656}

\begin{axis}[
  xmin = 2,
  xmax = 4,
  ymin = 0,
  ymax = 5,
  xlabel = {$r$},
  ylabel = {$E$},
  after end axis/.code = {
    \path (axis cs:4.0,1.6) node[right] {B3LYP};
  } 
] 

\def\ezero{-1.11}
\addplot+ table[x expr={\thisrowno{0}*2*\angs}, y expr={(\thisrowno{2}-\ezero)*\ev}] {data.dat};

\end{axis}

\end{tikzpicture}
\end{document}

It has to problems:

  1. I'd like to give the code next to \addplot, and not in the axis options.
  2. I'd like the coordinates (in particular the ordinate) to be calculated automatically.

This shows the result with the following data.dat file:

2.0 -13840.8142382 -0.8142382
2.1 -13840.9230067 -0.9230067
2.2 -13840.9967745 -0.9967745
2.3 -13841.0454158 -1.0454158
2.4 -13841.0762998 -1.0762998
2.5 -13841.0944654 -1.0944654
2.6 -13841.1038383 -1.1038383
2.7 -13841.1070221 -1.1070221
2.8 -13841.1059849 -1.1059849
2.9 -13841.1022183 -1.1022183
3.0 -13841.0966277 -1.0966277
3.1 -13841.0899909 -1.0899909
3.2 -13841.0828688 -1.0828688
3.3 -13841.0755779 -1.0755779
3.4 -13841.0687860 -1.0687860
3.5 -13841.0626993 -1.0626993
3.6 -13841.0572297 -1.0572297
3.7 -13841.0527363 -1.0527363
3.8 -13841.0493218 -1.0493218
3.9 -13841.0467450 -1.0467450
4.0 -13841.0447949 -1.0447949
4.1 -13841.0433105 -1.0433105
4.2 -13841.0421877 -1.0421877
4.3 -13841.0413471 -1.0413471
4.4 -13841.0407159 -1.0407159
4.5 -13841.0402353 -1.0402353
4.6 -13841.0398710 -1.0398710
4.7 -13841.0395993 -1.0395993
4.8 -13841.0393960 -1.0393960
4.9 -13841.0392397 -1.0392397
5.0 -13841.0391747 -1.0391747

test plot

PS. Another question as a bonus: is there a way to use the numbers in the 2nd column, rather than the 3rd (which is just the 2nd + 13840), without losing precision?

Jellby
  • 3,323

1 Answers1

8

You can use the code from pgfplots - Placing Nodes on x Coordinates of a Plot for this. It allows you to write

\addplot+ [add node at x={4}{[anchor=west]B3LYP}] table ...

(or

`\addplot+ [add node at x={\pgfkeysvalueof{/pgfplots/xmax}}{[anchor=west]B3LYP}] table...

if you don't want to specify the x value manually) to get

Note that you have to set clip mode=individual if you're using plot styles without markers to prevent the node from being clipped away.

\documentclass{article}
\usepackage{pgfplots}
\usetikzlibrary{intersections}
\begin{document}
\begin{tikzpicture}

\makeatletter
\def\parsenode[#1]#2\pgf@nil{%
    \tikzset{label node/.style={#1}}
    \def\nodetext{#2}
}

\tikzset{
    add node at x/.style 2 args={
        name path global=plot line,
        /pgfplots/execute at end plot visualization/.append={
                \begingroup
                \@ifnextchar[{\parsenode}{\parsenode[]}#2\pgf@nil
            \path [name path global = position line #1-1]
                ({axis cs:#1,0}|-{rel axis cs:0,0}) --
                ({axis cs:#1,0}|-{rel axis cs:0,1});
            \path [xshift=1pt, name path global = position line #1-2]
                ({axis cs:#1,0}|-{rel axis cs:0,0}) --
                ({axis cs:#1,0}|-{rel axis cs:0,1});
            \path [
                name intersections={
                    of={plot line and position line #1-1},
                    name=left intersection
                },
                name intersections={
                    of={plot line and position line #1-2},
                    name=right intersection
                },
                label node/.append style={pos=1}
            ] (left intersection-1) -- (right intersection-1)
            node [label node]{\nodetext};
            \endgroup
        }
    }
}

\def\angs{0.529177208354}
\def\ev{27.2113838656}

\begin{axis}[
  xmin = 2,
  xmax = 4,
  ymin = 0,
  ymax = 5,
  xlabel = {$r$},
  ylabel = {$E$},
  cycle list name = linestyles*,
  clip mode=individual
] 

\def\ezero{-1.11}
\addplot+ [,add node at x={4}{[anchor=west,]B3LYP}]
 table[x expr={\thisrowno{0}*2*\angs}, y expr={(\thisrowno{2}-\ezero)*\ev}] {
2.0 -13840.8142382 -0.8142382
2.1 -13840.9230067 -0.9230067
2.2 -13840.9967745 -0.9967745
2.3 -13841.0454158 -1.0454158
2.4 -13841.0762998 -1.0762998
2.5 -13841.0944654 -1.0944654
2.6 -13841.1038383 -1.1038383
2.7 -13841.1070221 -1.1070221
2.8 -13841.1059849 -1.1059849
2.9 -13841.1022183 -1.1022183
3.0 -13841.0966277 -1.0966277
3.1 -13841.0899909 -1.0899909
3.2 -13841.0828688 -1.0828688
3.3 -13841.0755779 -1.0755779
3.4 -13841.0687860 -1.0687860
3.5 -13841.0626993 -1.0626993
3.6 -13841.0572297 -1.0572297
3.7 -13841.0527363 -1.0527363
3.8 -13841.0493218 -1.0493218
3.9 -13841.0467450 -1.0467450
4.0 -13841.0447949 -1.0447949
4.1 -13841.0433105 -1.0433105
4.2 -13841.0421877 -1.0421877
4.3 -13841.0413471 -1.0413471
4.4 -13841.0407159 -1.0407159
4.5 -13841.0402353 -1.0402353
4.6 -13841.0398710 -1.0398710
4.7 -13841.0395993 -1.0395993
4.8 -13841.0393960 -1.0393960
4.9 -13841.0392397 -1.0392397
5.0 -13841.0391747 -1.0391747
};

\end{axis}

\end{tikzpicture}
\end{document}
Jake
  • 232,450
  • Perfect... now it only has to work with cycle list name = linestyles* :) – Jellby May 20 '13 at 16:07
  • @Jellby: You need to add clip mode=individual in that case... – Jake May 20 '13 at 16:32
  • Thanks. There's still something wrong, when I add more lines all the labels are at the same position, but I cannot reproduce that in the sample file... I'll come back when I find the reason or a non-working example. – Jellby May 20 '13 at 17:02
  • Without the options cycle list name=linestyles* and clip mode=individual the execute at end plot visualization gets executes twice. – Qrrbrbirlbel May 20 '13 at 20:35
  • @Qrrbrbirlbel: Does it? How do you know? And when does it matter? – Jake May 20 '13 at 20:44
  • The execute at end plot visualization code may not get executed twice, but the add node at x style gets with the + and without the mentioned options. To test it, add \newcounter{test} to the preamble and /utils/exec=\stepcounter{test}\errmessage{\arabic{test}} to the add node at x style. If you use the style twice ([add node at x={3}{B4LYP},add node at x={4}{B3LYP}]), you will get something similar to what @Jellby reported. – Qrrbrbirlbel May 20 '13 at 21:07
  • That might be a reason, another problem occurs when the label is placed exactly at the limit of the data (in this case, add node at x={5}, but replacing x expr with x index=0. Would it be possible to use the intersection or the last point in the plot if there is no intersection? – Jellby May 21 '13 at 07:22