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.

Please consider the following plot (code see bottom). The curves are the result of the function q[D]=sqrt(2*s*D/h), whereas h=0.01 and s is equal to 0.1 (blue) respectively 0.01 (green).

pgfplot

Now, I would like to add two more axis on the top of the upper plot as in the following plot. These two axis must be scaled via the function n[D]=D/(q[D])=sqrt(D*h/(2*s)). Maybe there is an alternative workaround of which I did not think up to now?

keynoteplot

\documentclass[11pt]{article}
\usepackage{tikz}
\usepackage{pgfplots}

\begin{document}

\begin{tikzpicture}
  \begin{axis}[
    xlabel=$D$,
    ylabel={$q$},axis x line=bottom, axis y line=left
  ] 
    \addplot[blue,mark=none,domain=0:100, samples=50, smooth,enlargelimits=upper] {sqrt(2*0.1*x/0.01)}; 
    \addplot[green,mark=none,domain=0:100, samples=50, smooth,enlargelimits=upper] {sqrt(2*0.01*x/0.01)}; 
  \end{axis}
\end{tikzpicture}

\end{document}
share|improve this question

2 Answers 2

up vote 6 down vote accepted

You can use "dummy" axis environments inside the same tikzpicture to generate the axis lines above the plot. As long as you make sure that the axis ranges are the same, they will align nicely. To get the tick values, you can set xticklabel={\pgfmathparse{sqrt(\tick*0.01/(2*#1))}\pgfmathprintnumber{\pgfmathresult}} which will convert the D value to n(D). That will get you something similar to the Excel output you posted.

To one-up Excel, we can also only plot nice round tick values. We want to be able to specify which ticks to show (0, 1, 1.5 and 2, for example) and let PGFPlots figure out where on the axis these values go. This requires a bit of trickery: We can plot an invisible plot of the inverse of the n(D) function, with the independent variable (in this case n(D)) plotted on the y-axis, and the dependent one (D) plotted on the x axis. By using the option xtick=data, tick labels will only appear at the positions of the samples we specified.

This might seem like a lot of work, but once we've figured it out, we can wrap it in a little macro like \fakexaxis{<value for s>}{<vertical offset>}{<tick positions>} and then simply say

  \begin{axis}[
    xlabel=$D$,
    ylabel={$q$},axis x line=bottom, axis y line=left
  ] 
    \addplot[blue,mark=none,domain=0:100, samples=50, smooth,enlargelimits=upper] {sqrt(2*0.1*x/0.01)}; 
    \addplot[green,mark=none,domain=0:100, samples=50, smooth,enlargelimits=upper] {sqrt(2*0.01*x/0.01)}; 
  \end{axis}

 \fakexaxis{0.1}{7ex}{0,1,1.5,2}
 \fakexaxis{0.01}{2ex}{0,2,3,...,7}

to generate the following output. I'd say the effort is worth it...

\documentclass[11pt]{article}
\usepackage{tikz}
\usepackage{pgfplots}

\begin{document}

\newcommand{\fakexaxis}[3]{
  \begin{axis}[
    hide y axis,
    yshift=#2,
    axis x line=top,
    x axis line style={latex-},
    xlabel={$s=#1$}, every axis x label/.style={at={(1,1)}, anchor=west},
    domain=0:2,
    samples at={#3},
    xmin=0, xmax=100,
    % Convert from D to n(D)
    xticklabel={\pgfmathparse{sqrt(\tick*0.01/(2*#1))}\pgfmathprintnumber{\pgfmathresult}},
    % tick marks only at sample points
    xtick=data
  ]
  % Use the inverse function D = f(n(D)) to find values for D at which to place tick marks (don't actually draw the function)
  \addplot [draw=none] ({\x^2*2*#1/0.01},\x);
  \end{axis}
}

\begin{tikzpicture}
  \begin{axis}[
    xlabel=$D$,
    ylabel={$q$},axis x line=bottom, axis y line=left
  ] 
    \addplot[blue,mark=none,domain=0:100, samples=50, smooth,enlargelimits=upper] {sqrt(2*0.1*x/0.01)}; 
    \addplot[green,mark=none,domain=0:100, samples=50, smooth,enlargelimits=upper] {sqrt(2*0.01*x/0.01)}; 
  \end{axis}

 \fakexaxis{0.1}{7ex}{0,1,1.5,2}
 \fakexaxis{0.01}{2ex}{0,2,3,...,7}


\end{tikzpicture}

\end{document}
share|improve this answer
    
very nice approach! many thanks. –  John Feb 8 '13 at 15:12

This is not an answer, but to long for a comment. You could write something yourself, possibly using the \foreach and define function possibilities of TikZ, but I can't get this to work inside the axis. Maybe someone can shed some light?

\documentclass[11pt]{article}
\usepackage{tikz}
\usepackage{pgfplots}

\begin{document}

\pgfmathsetmacro{\h}{0.01}
\pgfmathsetmacro{\sOne}{0.1}
\pgfmathsetmacro{\sTwo}{0.01}

\begin{tikzpicture}[
    declare function={
        n(\d)= sqrt(\d*\h/(2*\sOne));
    }
  ]
  \begin{axis}[
    xlabel=$D$,
    ylabel={$q$},axis x line=bottom, axis y line=left
  ] 
    \addplot[blue,mark=none,domain=0:100, samples=50, smooth,enlargelimits=upper] {sqrt(2*\sOne*x/\h)}; 
    \addplot[green,mark=none,domain=0:100, samples=50, smooth,enlargelimits=upper] {sqrt(2*\sTwo*x/\h)}; 

  \end{axis}
    \foreach \d in {5, 20, 35, 50, 65, 80, 95}
    {
        \node at (0.1*\d,-50pt) {\pgfmathparse{n(\d)}\pgfmathresult};
    } 
\end{tikzpicture}
\end{document}

gives you: Plot with extra labels

Alternatively, maybe you could compute the ticklabels with another program/script, and include them with xticklabels from table (Section 4.14) in the pgfplotsmanual.

share|improve this answer

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.