colorbar with definite number of discrete colours; with matching ticks placement
Explicit setting of the colour bar ticks using
colorbar style={
ytick={<first>,<first>+(<last>-<first>)/<levels>,...,<last>}
}
does the trick.
The three ticklist elements <first>,<second>,...,<last>
must be calulated based on the values of /pgfplots/point meta min
and /pgfplots/point meta max
and the desired number of colour <levels>
.
However, the PGF-provided math parsing facilities \pgfmathparse{...}
and \pgfmathresult
seem to be unusable for the evaluation of floating point expressions in the axis configuration. Nor may \pgfkeysvalueof{/pgfplots/point meta min}
and \pgfkeysvalueof{/pgfplots/point meta max}
be directly used inside ytick={...}
to set the limits.
Most fortunately, there is the LaTeX3 expandable math parser \fp_eval:n{...}
which graciously accomplishes the tick calculation and which is also used to wrap the lower and upper tick limits.
UPDATE
As of PGFPlots-1.14, \pgfkeysvalueof{/pgfplots/point meta max}
returns values with leading and trailing characters which do not belong to the fp numbers and cause \fp_eval:n
to fail inside ytick={...}. As a workaround the calculations are moved into every tick/.append code={...}
.
Example with 13 colour levels:
Code for current PGFPlots-1.14:
\documentclass[tikz,border=3pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.14}
\usepackage{expl3}
\ExplSyntaxOn
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \fpEval{<expression>}
% expandably evaluate floating point <expression>
\let\fpEval\fp_eval:n
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\begin{axis}[
domain=-2:2,
view={0}{90},
colormap={CM}{
samples of colormap=(13 of hot)},
colormap access=piecewise constant,
colorbar right,
colorbar style={%
ytick={%
\aval,\bval,...,\cval%
% \fpEval{\pgfkeysvalueof{/pgfplots/point meta min}},%
% \fpEval{\pgfkeysvalueof{/pgfplots/point meta min}+(\pgfkeysvalueof{/pgfplots/point meta max}-\pgfkeysvalueof{/pgfplots/point meta min})/13},
% ...,
% \fpEval{2*\pgfkeysvalueof{/pgfplots/point meta max}}
},
every tick/.append code={%
\xdef\aval{\fpEval{\pgfkeysvalueof{/pgfplots/point meta min}}}
\xdef\bval{\fpEval{\pgfkeysvalueof{/pgfplots/point meta min}+(\pgfkeysvalueof{/pgfplots/point meta max}-\pgfkeysvalueof{/pgfplots/point meta min})/13}}
\xdef\cval{\fpEval{2*\pgfkeysvalueof{/pgfplots/point meta max}}}
}
},
]
\addplot3[surf,shader=interp]
{exp(-x^2-y^2)*x};
\end{axis}
\end{tikzpicture}
\end{document}
Code for previous PGFPlots-1.13:
\documentclass[tikz,border=3pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.13}
\usepackage{expl3}
\ExplSyntaxOn
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \fpEval{<expression>}
% expandably evaluate floating point <expression>
\let\fpEval\fp_eval:n
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\begin{axis}[
domain=-2:2,
view={0}{90},
colormap={CM}{
samples of colormap=(13 of hot)},
colormap access=piecewise constant,
colorbar right,
colorbar style={%
ytick={%
\fpEval{\pgfkeysvalueof{/pgfplots/point meta min}},%
\fpEval{\pgfkeysvalueof{/pgfplots/point meta min}+(\pgfkeysvalueof{/pgfplots/point meta max}-\pgfkeysvalueof{/pgfplots/point meta min})/13},%
...,%
\fpEval{\pgfkeysvalueof{/pgfplots/point meta max}*2} %increase limit to ensure placement of uppermost tick label
}
}
]
\addplot3[surf,shader=interp]
{exp(-x^2-y^2)*x};
\end{axis}
\end{tikzpicture}
\end{document}
Use ytick=data
:
\documentclass[tikz,border=3pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.13}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
domain=-2:2,
view={0}{90},
colormap={CM}{
samples of colormap=(13 of hot)},
colormap access=piecewise constant,
colorbar right,
colorbar style={%
ytick=data,
}
]
\addplot3[surf,shader=interp]
{exp(-x^2-y^2)*x+0.5};
\end{axis}
\end{tikzpicture}
\end{document}
This requires pgfplots 1.14 (the most recent stable).
Note that the image is 1:1 equivalent to
\documentclass[tikz,border=3pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.13}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
domain=-2:2,
view={0}{90},
colorbar right,
colorbar style={%
ytick=data,
}
]
\addplot3[contour filled={number=13}]
{exp(-x^2-y^2)*x+0.5};
\end{axis}
\end{tikzpicture}
\end{document}
except that contour filled
allows somewhat more freedom to choose the contour positions.