3

Please consider this MWE:

\begin{document}
\begin{tikzpicture}

\begin{axis}[%
    /pgf/number format/1000 sep={}, % do not delimit per thousand
    xmin=19,
    xmax=22.5,
    xlabel={angle in degree},
    xtick pos=left, % bottom ticks
    grid=none,
    % FIXME: "extra x ticks" should be calculated from xstart, xinc, xend
    % xstart=4500; xinc=-250; xend=4000;
    % The x tick values below are calculated by: x=4250; asind(1500/x)
    extra x ticks={22.02431, 20.66731, 19.47122}, % FIX ME
    every extra x tick/.style={
        xtick pos=right, % top ticks
        xticklabel pos=right, % top tick labels
        xticklabel={
            \pgfmathparse{1500/sin(\tick)}
            \pgfmathprintnumber{\pgfmathresult} m/s
            },
        xticklabel style={
            /pgf/number format/.cd,fixed,fixed zerofill,precision=0,/tikz/.cd,
            },
        },
    ]
    \addplot[red,samples at={19,19.1,...,23}] {x};
\end{axis}
\end{tikzpicture}

\end{document}

enter image description here

I plot data (here a linear function) that depends on the variable x, which is here an angle in degree. Now I would like to add a second x-axis on top. Pgfplots does not support this nicely as is discussed here in several other questions. I took the approach of defining extra x ticks and position them on the top.

There I would like to plot a velocity, that is linked to the angle by the formula v=asind(1500/angle). I know want to have velocities with an increment of 250 put on the top axis, e.g. 4500, 4250 and 4000. The line marked with FIX ME defines my issue: I would like to apply that formula to calculate the x-axis locations, that correspond to the velocities. The angle values of extra x ticks are taken in xticklabel and converted back to velocities. This is needed due to the nonlinear relationship of the two axis. A minor issue is that the precision of PGF is limited (4251 instead of 4250). I tried /pgf/fpu=true...

Hopefully I expressed my question clearly.

  • 1
    I'm not sure I understand exactly what you're trying to do. Do you want to automate the position of the yticks instead of providing the list? In that case, you can simply say ytick=data instead of ytick={0,1,4,9,16,25}. – Jake Mar 20 '15 at 14:58
  • @Jake, I clarified my question and adapted the example to make it easier to understand what I try to achieve. – Peter Pablo Mar 20 '15 at 15:05
  • I still don't really understand what your aim is: in the example, you place y ticks at 0, 2, 4, 8, 16 and 24, but then you mention that you want to be able to provide \ystart, \yincrement and \yend, which sounds like you want to split the y axis in a linear fashion. Maybe it would be a good idea if you described the final result you want to get, and not the way you want to get there. – Jake Mar 20 '15 at 15:10
  • Alright! I wanted to simplify the question but that really isn't working so well. Let me rephrase... – Peter Pablo Mar 20 '15 at 15:11
  • 1
    @PeterPablo I updated my answer! – darthbith Mar 20 '15 at 15:56
2

The below is based on the answer of Claudio, here. We have to do some machinations with macros to get this to work, but we can define a new command that does the processing and sets macros for the ticks and the labels. pgfplots also doesn't like to have macros in label definitions in the plot (I don't remember why) so we have to use the \edef construct. This fixes the precision problem, since we don't have to do any computations to set the label.

The syntax of the \deflistticks is the same as for all pgf for loops: start element,second element,...,end element, where the difference between start element and second element sets the increment. You can also use an explicit list of all the coordinates.

The \deflisttick macro works by defining two global macros (\gdef), \extraticks and \listlabels. These global macros will contain the lists of ticks and labels, respectively, that we want to set. The first thing we do is find the number of items in the input list (#1 is the input). Then we loop through the list and do the computations on the passed in values; note that pgf operates in degrees by default. Then we fill our lists. If the element is the last one of the list, we don't append a comma.

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}

\newcommand{\deflisttick}[1]{
    \gdef\extraticks{}
    \gdef\listlabels{}
    \foreach \x[count=\xi] in {#1}{\global\let\maxitems\xi}
    \foreach \x[count=\xi] in {#1}{
        \pgfmathsetmacro{\xy}{asin(1500/\x)}
        \ifnum\xi=\maxitems
            \xdef\extraticks{\extraticks \xy}
            \xdef\listlabels{\listlabels \x\ m/s}
        \else
            \xdef\extraticks{\extraticks \xy,}
            \xdef\listlabels{\listlabels \x\ m/s,}
        \fi
    }
}
\deflisttick{4000,4250,...,4500}
\edef\temp{%
  \noexpand\pgfplotsset{%
      extra x tick labels list/.style={xticklabels={\listlabels}}
  }%
}
\temp
\begin{document}
\begin{tikzpicture}

\begin{axis}[%
    /pgf/number format/1000 sep={}, % do not delimit per thousand
    xmin=19,
    xmax=22.5,
    xlabel={angle in degree},
    xtick pos=left, % bottom ticks
    grid=none,
    % FIXME: "extra x ticks" should be calculated from xstart, xinc, xend
    % xstart=4500; xinc=-250; xend=4000;
    % The x tick values below are calculated by: x=4250; asind(1500/x)
    % extra x ticks={22.02431, 20.66731, 19.47122}, % FIX ME
    extra x ticks={\extraticks},
    every extra x tick/.style={
        xtick pos=right, % top ticks
        xticklabel pos=right, % top tick labels
        extra x tick labels list,
        },
    ]
    \addplot[red,samples at={19,19.1,...,23}] {x};
\end{axis}
\end{tikzpicture}

\end{document}

enter image description here

  • Thank you very much! I will evaluate your answer. Please note that I updated my question, as was suggested by Jake. – Peter Pablo Mar 20 '15 at 15:37
  • @PeterPablo Yes, I just commented on the question :-) – darthbith Mar 20 '15 at 15:38
  • Unfortunately I am struggling with putting \ylistticks in extra x ticks. hmmm...: Dimension too large. --- wait... Got it! Will adapt the answer soon. Some polishing to do. – Peter Pablo Mar 20 '15 at 15:48
  • I got it as well, with better formatting of the labels. I will fix it momentarily. – darthbith Mar 20 '15 at 15:51
  • 1
    @PeterPablo See the update! – darthbith Mar 20 '15 at 15:56

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.