pgfplots mit nichtlinear skalierten Farbkarten

pgfplots mit nichtlinear skalierten Farbkarten

Dies hier ist eine Frage, die auf der pgfplots-Mailingliste gestellt wurde; ich beantworte sie hier, da dies eine qualitativ hochwertigere Antwort ermöglicht.


Ich habe ein Bild, das eine divergierende Farbkarte verwendet.

In diesem Fall haben Minimum und Maximum nicht den gleichen absoluten Wert (sondern stattdessen -0,2 und +0,5).

Ich möchte eine „zentrierte Farbkarte“ erstellen können, bei der „0“ die mittlere Farbe ist, alle Punkte >0 die obere Hälfte der Karte verwenden und alle <0 die untere Hälfte.

Der Farbbalken sollte entsprechend den tatsächlichen Werten verzerrt sein (d. h. die untere Hälfte der Karte sollte 2/7 des Balkens einnehmen und die obere Hälfte die restlichen 5/7).

\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}

Bildbeschreibung hier eingeben

vielleicht ein Punkt-Meta-Center=[auto,]-Schlüssel, wobei auto einen berechneten Wert von (Punkt-Meta-Max + Punkt-Meta-Min) ÷ 2 bedeutet

Antwort1

Es ist möglich, die zu skalieren point meta. Natürlich wird dadurch auch die colorbarund ihre Achsenbeschreibungen skaliert. Da aber a colorbareigentlich nichts anderes als ein normales ist axis, können wir benutzerdefinierte Transformationen definieren, um den Effekt „rückgängig zu machen“.

Der folgende Code definiert einen neuen Stil nonlinear colormap around 0={<min>}{<max>}, der die Punktmetadaten neu skaliert (vorausgesetzt, dass dies ystandardmäßig die Koordinate gewesen wäre). Außerdem wird die Farbleiste auf nichtlineare Weise neu skaliert, um die korrekten Beschreibungen wiederherzustellen:

Bildbeschreibung hier eingeben

\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}

verwandte Informationen