# Pgfplots with 2nd y-axis and "non-linearly" converted units

I want to plot a diagram in which I display scattered values within a certain range - these are the maximum values of a measurement I made. From these values, a parameter can be calculated through a formula containing a square root (let's assume y_2=\sqrt{a \cdot y_1}). I would like to show a second y-axis y_2 from which the obtained parameter can directly be read off. I have included an example of what the diagram could look like (created in pyplot).

Unfortunately, I have not yet found a way on how I could obtain a second y-axis for a pgfplot that is not "linearly dependent" on the first y-axis. Does anybody have an idea on what I have to do to generate such a graph with pgfplots?

It is possible to add annotations to a plot, to place them according to axis coordinates, to retrieve the axis xmin, xmax, ymin and ymax values, etc. Therefore, with a bit of care due to how pgfplots executes code in the axis environment (cf. Utility Commands in chapter Utilities and Basic Level Commands of the pgfplots manual), one can draw this custom secondary scale.

The following code reproduces your plot, where you appear to have used y2 = sqrt(ay1) with a = 5. In order to use this particular function, my code specifies the function and its reciprocal:

declare function={y2(\x) = sqrt(5*\x);
y1(\x) = \x^2/5;}


The loop maximum value is automatically determined using the expression given for y2 and the ymax value for the plot. One could do the same to determine the minimum loop value in function of ymin, but I prefer manually setting it to 0, otherwise should you lower ymin below 0, you would obtain errors (trying to take the square root of a negative number).

I use the PGF fpu library in places where computations are done so that this solution has good chances to work as well with other functions where intermediate results might have a very small or a very large magnitude.

Full example:

\documentclass[tikz, border=2mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

\newif\ifmyInsideAxis

\begin{document}

\begin{tikzpicture}
\begin{axis}[ymin=0, ymax=10, clip=false, grid,
declare function={y2(\x) = sqrt(5*\x);
y1(\x) = \x^2/5;},
ylabel={$y_1$},
execute at end axis={
\edef\myYmin{\pgfkeysvalueof{/pgfplots/ymin}}
\edef\myYmax{\pgfkeysvalueof{/pgfplots/ymax}}
%
\begingroup
\pgfset{fpu=true}
% Two values given at the start → the pgfmath parser is used.
\pgfplotsinvokeforeach {0,1,...,{int(ceil(y2(\myYmax)))}} {
\pgfmathparse{y1(#1)} \pgfmathfloattofixed{\pgfmathresult}
\edef\currentY{\pgfmathresult}
%
\myInsideAxistrue
\ifdim \currentY pt>\myYmax pt \myInsideAxisfalse
\else \ifdim \currentY pt< \myYmin pt \myInsideAxisfalse \fi
\fi
%
\edef\temp{
\ifmyInsideAxis
\noexpand\path
(current axis.east |- 0,0) ++(axis direction cs:0,\currentY)
coordinate (m);
\noexpand\draw
(m) -- ([xshift=\pgfkeysvalueof{/pgfplots/minor tick length}]m)
node[font=\noexpand\tiny, right] {\noexpand\pgfmathprintnumber{#1}};
\fi
}
{\pgfset{fpu=false} \temp}
} % end of \pgfplotsinvokeforeach's body
\endgroup
}]
\node[rotate=90] at ([xshift=2em]current axis.east) {$y_2 = \sqrt{a y_1}$};