Symmetric (Diverging) log color scale

68 visualizaciones (últimos 30 días)
Danielle Lemmon
Danielle Lemmon el 20 de Abr. de 2022
Editada: DGM el 30 de Dic. de 2023
I'm trying to figure out how to make a symmetric (diverging) logarithmic color map/scale. Does anyone have any solutions to go from something like the bottom graph (linear diverging color map) to the top one (logarithmic diverging colormap)? I'd normally start with a color map from cbrewer2 (great download, would highly recommend). But then if I use "set(gca,'ColorScale','log')" it only captures small vs big positive values, not small vs big for both positive vs negative values.
There is a matplotlib function that does exactly this, but having trouble turning it into MATLAB code
https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.SymLogNorm.html?highlight=symlognorm#matplotlib.colors.SymLogNorm

Respuestas (2)

DGM
DGM el 30 de Dic. de 2023
Editada: DGM el 30 de Dic. de 2023
Here's a shoddy example, but at least it does what's described.
% let A be your data
% note that the data is asymmetric and ends in the middle of a decade
A = linspace(-50, 500, 1000);
% plot A
% i'm going to plot xdata just for sake of giving some scale information
imagesc(signedlog10(A),'xdata',A) % represented in signed log10
% use a symmetric colormap
% MATLAB doesn't really have any good symmetric diverging colormaps
% but this will have to do
colormap(turbo(256))
% get the minimum and maximum value of A
% this needs to be symmetric unless you also make a
% custom asymmetric divergent colormap
crange = [-1 1]*max(abs(imrange(A))); % make symmetric
crange = round(signedlog10(crange)); % you may choose to round to integer values
% set limits for the caxis
caxis(crange); % represented in signed log10
% create ticks, ticklabels
% choose nticks as desired
nticks = 4;
ticklabels = logspace(0,max(crange),nticks);
ticklabels = [-flip(ticklabels) 0 ticklabels]; % make symmetric
% set Ticks and TickLabels
colorbar('Ticks',signedlog10(ticklabels),'TickLabels',ticklabels)
function out = signedlog10(in)
% naive signed-log
%out = sign(in).*log10(abs(in));
% modified continuous signed-log
% see Measurement Science and Technology (Webber, 2012)
C = 0; % controls smallest order of magnitude near zero
out = sign(in).*(log10(1+abs(in)/(10^C)));
end
See also:
and look at the link provided by OP for symlognorm
Note the different approach I used for solving this problem. I leveraged my eyeballs, fingers, and brain to read and comprehend the question and references. I then wrote some code using the aforementioned tools. It's not perfect, generalized, or timely, but it's enough to demonstrate a method similar to the one requested.
While I don't always have a satisfactory answer, I'm not in the habit of asking an AI to generate a code-like collage of text on my behalf and then insincerely pretending that it works without even spending a moment's glance to check that it does.
Providing actual value is less time-efficient than providing the illusion of value. It seems that there are a lot of very efficient users on the forum these days.

Ishu
Ishu el 29 de Dic. de 2023
Hi Danielle,
I understand you want symmetric logarithmic colorbar using "log" property of "ColorScale" but you are getting only positive values.
As the logarithm of a negative number or zero is undefined in the real number system so "set(gca, 'ColorScale', 'log')" only works with positive values. There is a manual approach that you can follow.
% data with both positive and negative values
data = linspace(-200, 100, 1000);
% Display the data
imagesc(data);
colormap('jet'); %set according to your data
% Create a symmetrical log scale for the colorbar
cb = colorbar;
% Set colorbar ticks and labels manually to simulate a symmetrical log scale
caxis([-max(abs(data(:))) max(abs(data(:)))]);
ticks = [-100 -10 -1 1 10 100 1000];
tickLabels = arrayfun(@num2str, ticks, 'UniformOutput', false);
% Apply the ticks and labels to the colorbar
set(cb, 'Ticks', log10(ticks(ticks > 0)), 'TickLabels', tickLabels);
% Adjust the color limits to the data
set(gca, 'CLim', log10([min(ticks(ticks > 0)) max(ticks)]));
For more information on "colorbar" you can follow below documentation:
Hope it helps!
  1 comentario
DGM
DGM el 29 de Dic. de 2023
Yes, a manual approach is needed, but did you even look at the output of the code you pasted?

Iniciar sesión para comentar.

Categorías

Más información sobre Colormaps en Help Center y File Exchange.

Community Treasure Hunt

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

Start Hunting!

Translated by