# Heatmap log colour scale: caxis() doesn't map values correctly?

37 views (last 30 days)
Duncan Ingram on 1 Dec 2021
Commented: Duncan Ingram on 1 Dec 2021
I have a 2D array with logarithmically distributed values from [1e-5, 1e5]. For various reasons, I want to change the colourbar with limits beyond this range. I do this using caxis, e.g. caxis([a,b]), where a and b are the desired exponents. However the resulting colourbar does not map correctly.
Example problem, starting with log-distributed values and desired limits of [1e-5, 1e5]:
% Create log values and generate heatmap
dim = 10;
x = logspace(-5,5,dim);
values = repmat(x,[dim,1]);
hm = heatmap(values);
% Make visually clearer
hm.GridVisible = 'off';
colormap default
ax1 = gca;
ax1.XDisplayLabels = nan(length(ax1.XDisplayData),1);
ax1.YDisplayLabels = nan(length(ax1.YDisplayData),1);
% Colour bar scaling - PROBLEM
set(gca,'ColorScaling','log') % Log scale
caxis([-5,5]) % Lower/Upper limits (exponents) (to change!)
ax2 = struct(gca);
cb = ax2.Colorbar;
cb.Ticks = [1e0,1e1,1e2,1e3,1e4,1e5]; % Example ticks to show problem...
After the limits are specified, the colour mapping becomes skewed. If you pause the code after the 'set' line, the caxis values give [-11.5, 11.5], not [-5, 5]. Therefore, if I desire a fixed colour range such as [1e-7, 1e7], I apparently need to fudge the values. What's going on? Does caxis() not define exponents in the way that it should?

DGM on 1 Dec 2021
Edited: DGM on 1 Dec 2021
You're expecting that caxis expects log10(limits). It's actually expecting the natural log.
% Create log values and generate heatmap
dim = 11; % just so the data labels show up
x = logspace(-5,5,dim);
values = repmat(x,[dim,1]);
hm = heatmap(values);
% Make visually clearer
hm.GridVisible = 'off';
colormap default
ax1 = gca;
ax1.XDisplayLabels = nan(length(ax1.XDisplayData),1);
ax1.YDisplayLabels = nan(length(ax1.YDisplayData),1);
% Colour bar scaling
set(gca,'ColorScaling','log') % Log scale
caxis(log([x(1) x(end)])); Now you should be able to set arbitrary caxis limits.
% caxis(log([1E-7 1E7]));
##### 1 CommentShowHide None
Duncan Ingram on 1 Dec 2021
Ahh thank you so much! Natural log vs. log10 went through my head at some point, but for some reason I never took it further. The log([a b]) conversion is so simple yet explains all my 'scaling issues' perfectly.

### More Answers (1)

Mathieu NOE on 1 Dec 2021
hello
no mre problem my friend ! % Create log values and generate heatmap
dim = 10;
x = logspace(-5,5,dim);
values = repmat(x,[dim,1]);
hm = heatmap(values);
% Make visually clearer
hm.GridVisible = 'off';
ax1 = gca;
ax1.XDisplayLabels = nan(length(ax1.XDisplayData),1);
ax1.YDisplayLabels = nan(length(ax1.YDisplayData),1);
% Colour bar scaling
N = 256; % colorbar discrete values
cmap = colormap(jet(N)) ; %Create Colormap
set(gca,'ColorScaling','log') % Log scale
ax2 = struct(gca);
cbh = ax2.Colorbar;
tmp = logspace(min(log10(values),[],'all'), max(log10(values),[],'all'), dim+1);
cbh.Ticks = tmp ; %Create N ticks from min to max of Z array
cbh.TickLabels = num2cell(tmp) ; %Replace the labels of these N ticks with the numbers defined in "tmp"
##### 1 CommentShowHide None
Duncan Ingram on 1 Dec 2021
Thanks for this example, however it doesn't solve my general problem of specifying a general range for the colourbar. E.g. how would I create an equivalent heatmap with a colourbar from [1e-7, 1e7] (with the same data!).
Also, I can achieve the same result as your example by simply stopping my code after the 'set' line.

R2020b

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!