pgfplots con mapas de color escalados no linealmente

pgfplots con mapas de color escalados no linealmente

Esta es una pregunta que apareció en la lista de correo de pgfplots; Lo respondo aquí ya que esto permite una respuesta de mayor calidad.


Tengo una imagen que usa un mapa de colores divergentes.

En este caso, el mínimo y el máximo no tienen el mismo valor absoluto (sino -0,2 y +0,5)

Quiero poder hacer un "mapa de color centrado", donde "0" es el color medio, todos los puntos >0 usan la mitad superior del mapa y todos los <0 la mitad inferior.

La barra de color debe estar sesgada según los valores reales (es decir, la mitad inferior del mapa debe ocupar 2/7 de la barra y la mitad superior los 5/7 restantes).

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


\begin{document}
\begin{tikzpicture}

\begin{axis}[
    enlargelimits=false,
    % I want the color to be distributed in a nonlinear way, not like this
    % I want the tick labels to reflect the centered colorbar
    colorbar,
]
    \addplot[line width=3pt,mesh,domain=-0.2:0.5] {x};
\end{axis}
\end{tikzpicture}

\end{document}

ingrese la descripción de la imagen aquí

tal vez un punto meta centro = tecla [auto,], donde auto significa un valor calculado de (punto meta máximo + punto meta mínimo) ÷ 2

Respuesta1

Es posible escalar el point meta. Naturalmente, esto también escalará las colorbardescripciones de sus ejes. Pero como a colorbaren realidad no es más que normal axis, podemos definir transformaciones personalizadas para "deshacer" el efecto.

El siguiente código define un nuevo estilo nonlinear colormap around 0={<min>}{<max>}que cambia la escala del metapunto (asumiendo que habría sido la ycoordenada por defecto). También cambia la escala de la barra de colores de forma no lineal para restaurar las descripciones correctas:

ingrese la descripción de la imagen aquí

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

\pgfplotsset{
    % this transformation ensures that every input argument is
    % transformed from -0.2 : 0.5 -> -0.5,0.5 
    % and every tick label is transformed back:
    nonlinear colormap trafo/.code 2 args={
        \def\nonlinearscalefactor{((#2)/(#1))}%
        \pgfkeysalso{%
            y coord trafo/.code={%
                \pgfmathparse{##1 < 0 ? -1*##1*\nonlinearscalefactor : ##1}%
            },
            y coord inv trafo/.code={%
                \pgfmathparse{##1 < 0 ? -1*##1/\nonlinearscalefactor : ##1}%
            },
        }%
    },
    nonlinear colormap around 0/.code 2 args={
        \def\nonlinearscalefactor{((#2)/(#1))}%
        \pgfkeysalso{
            colorbar style={
                nonlinear colormap trafo={#1}{#2},
                %
                % OVERRIDE this here. The value is *only* used to
                % generate a nice axis, it does not affect the data.
                % Note that these values will be mapped through the
                % colormap trafo as defined above.
                point meta min={#1},
                point meta max={#2},
            },
            %
            % this here is how point meta is computed for the plot.
            % It means that a point meta of -0.2 will actually become -0.5
            % Thus, the *real* point meta min is -0.5... but we
            % override it above.
            point meta={y < 0 ? -y*\nonlinearscalefactor : y},
        }%
    },
}

\begin{document}
\begin{tikzpicture}

\begin{axis}[
    enlargelimits=false,
    colorbar,
    %
    % activate the nonlinear colormap:
    nonlinear colormap around 0={-0.2}{0.5},
    %
    % reconfigure it - the default yticks are typically unsuitable
    % (because they are chosen in a linear way)
    colorbar style={
        ytick={-0.2,-0.1,0,0.25,0.5},
    },
]
    \addplot[line width=3pt,mesh,domain=-0.2:0.5] {x};
\end{axis}
\end{tikzpicture}

\end{document}

información relacionada