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

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
DGM 2021년 12월 1일
편집: DGM 2021년 12월 1일
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

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.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Mathieu NOE
Mathieu NOE 2021년 12월 1일
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

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.

댓글을 달려면 로그인하십시오.

카테고리

도움말 센터File Exchange에서 Color and Styling에 대해 자세히 알아보기

제품

릴리스

R2020b

질문:

2021년 12월 1일

댓글:

2021년 12월 1일

Community Treasure Hunt

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

Start Hunting!

Translated by