Python's matplotlib
has an axis scale known as "Asinh". Close to zero, it behaves as a linear scale, but far away from zero, it behaves as a log scale. It is interesting for logarithmic scale plots that range over negative and positive numbers. Is it possible to implement such a scale in pgfplots
? Ideally, I'd like to know whether there is a manner of implementing it in such a way it can be accessed via ymode=asinh
, for example, which seems a bit different than what is achieved in this similar question.
1 Answer
Add the following lines to your preamble:
\usepackage{pgfplots}
\usetikzlibrary{math}
\tikzmath{
function asinhinv(\x,\a){
\xa = \x / \a ;
return \a * ln(\xa + sqrt(\xa*\xa + 1)) ;
};
function asinh(\y,\a){
return \a * sinh(\y/\a) ;
};
}
\pgfplotsset{
ymode asinh/.style = {
y coord trafo/.code={\pgfmathparse{asinhinv(##1,#1)}},
y coord inv trafo/.code={\pgfmathparse{asinh(##1,#1)}},
},
ymode asinh/.default = 1
}
To activate the mode asinh
, add the key ymode asinh
(without =
inbetween) to the options of the axis
environment. The key takes as an optional argument the scaling factor, with the default being 1
.
If you replace ymode asinh
by, say, ymode asinh=2
, the values around y=0
will be closer together.
\documentclass[tikz]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{math}
\tikzmath{
function asinhinv(\x,\a){
\xa = \x / \a ;
return \a * ln(\xa + sqrt(\xa*\xa + 1)) ;
};
function asinh(\y,\a){
return \a * sinh(\y/\a) ;
};
}
\pgfplotsset{
ymode asinh/.style = {
y coord trafo/.code={\pgfmathparse{asinhinv(##1,#1)}},
y coord inv trafo/.code={\pgfmathparse{asinh(##1,#1)}},
},
ymode asinh/.default = 1
}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
ymode asinh,
height=12cm,
legend pos=north west,
scaled ticks = base 10:0,
domain = -5:5.5,
ytick = {-100,-10, -1,0,1,10,100},
minor ytick = {-90,-80,...,-20,-9,-8,...,-2,-.9,-.8,...,.9,2,3,...,9,20,30,...,90},
yticklabel style={/pgf/number format/.cd,int detect,precision=0},
tick label style = {fill=white, fill opacity=.7},
yminorgrids = true,
ymajorgrids = true,
xmajorgrids = true,
samples=200,
axis lines=center,
]
\addplot+ [mark=none] {x} ;
\addplot+ [mark=none] {exp(x)} ;
\addplot+ [mark=none] {-exp(-x)} ;
\legend {$x$,$e^x$,$-e^{-x}$}
\end{axis}
\end{tikzpicture}
\end{document}
Sources: I started from the answer to Symlog as axis scaling in PGFPlots.
-
1Any idea why the lower y tick is -99.4 instead -100? I know pgf is not very precise, but not so imprecise. Anyway, two workarounds. First, replace
precision=2
byprecision=0
inyticklabel style=
, if you like scientific numbering. Second, more ugly, replace-100
by-101
inytick =
(because it gives -100.3, instead -99.4) AND replaceint detect,precision=2
byfixed,precision=0
inyticklabel style=
. You obtain then -100, -10, -1, 1, 10, 100 in the y axis. But it's probably better to find a real fix, the value -99.4 is far to away from -100. Why is -100 recalculated?– quark67Mar 7 at 15:18 -
@quark67 Thanks for the suggestions, I fixed it by
precision=0
. I also noted these rounding (?) errors, but didn't care, since the OP has probably a different application anyway.– gernotMar 7 at 16:56 -
This is wonderful, but I am particularly interested in the cases
ymode asinh=0.01
, for example (in fact, I'm going for1e-9
), but these cases with small parameters seem to lead to errors in your example, perhaps due to TeX's arithmetic capabilities? Is there a workaround? Mar 7 at 19:58 -
@NíckolasAlves You probably get
Dimension too large
. I think that tikzmath/TeX is not able to handle numbers in a wide range as one is used from ordinary real numbers with mantissa. You might have to reformulate the coordinate transformation to make sure that no intermediate result exceeds the admissible range, for the values that you use. I suggest to ask a new question, showing the code that you actually want to use. You might also want to search forDimension too large
to get an idea of the different causes. Sorry ...– gernotMar 7 at 20:39 -
@gernot Indeed it is
Dimension too large
. I'll see about asking a new, more specific question later. Thank you =) Mar 7 at 23:03