Nonlinear colormap for data that diverges
36 views (last 30 days)
Show older comments
I have data that goes through divergences where the Z value goes from approximately -4000 to 4000 very rapidly in certain regions, but the vast majority of the data is near zero. In the picture below, to be able to see what is going on I had to scale most of the color values to near zero to properly see what is happening. But in doing so, most of the colors are in the tiny sliver near zero and the red and blue take up the rest. I would like to nonlinearly scale the colorbar to be able to see all of the colors being used and greatly shrink the red and blue color part of the bar, with leaving the raw data as is if possible. It would also be nice if the colorbar ticks would vary nonlinear as well, instead of being forced to have a set number between consecutive ticks.
%Simple Model of divergent data
X = linspace(-2,2,501) + 0.002;
Y = linspace(-2,2,501) + 0.002;
%Function with Positive and Negative Divergence, and most values near 0
Z = zeros(501,501);
for i=1:length(X)
for j=1:length(Y)
Z(i,j) = 1/((X(i) - 1)^2 + (Y(j) - 1)^2) - 1/((X(i) + 1)^2 + (Y(j) + 1)^2) + 5*(cos(X(i))+sin(Y(i)));
end
end
%Setting the colormap
factor = 0.3;
cmap = jet(1000);
map = 999*rescale(1000./(1+exp(-factor*([1:1000]-500))));
cmap2 = cmap(1+fix(map),:);
figure('Position',[200,100,1500,730]);
ax=axes;
[X,Y] = meshgrid(X,Y);
surf(X,Y,Z,'linestyle','none');
a = colorbar;
set(ax,'colormap',cmap2)
view([0,90])
0 Comments
Accepted Answer
Voss
on 10 Feb 2024
Edited: Voss
on 11 Feb 2024
How about something like this:
%Simple Model of divergent data
X = linspace(-2,2,801) + 0.002;
Y = linspace(-2,2,501) + 0.002;
%Function with Positive and Negative Divergence, and most values near 0
Z = 1./((X - 1).^2 + (Y.' - 1).^2) - 1./((X + 1).^2 + (Y.' + 1).^2) + 5*(cos(X)+sin(Y.'));
Z_scaled = sign(Z).*log10(1+abs(Z));
figure('Position',[200,100,1500,730]);
surf(X,Y,Z_scaled,'LineStyle','none')
view(2)
colormap(jet(1000))
cb = colorbar();
tl = [-10.^(5:-1:1) 0 10.^(1:5)];
cb.Ticks = sign(tl).*log10(1+abs(tl));
cb.TickLabels = tl;
Edited to use Z_scaled = sign(Z).*log10(1+abs(Z)); instead of Z_scaled = sign(Z).*log10(abs(Z));
6 Comments
More Answers (1)
Morgan
on 10 Feb 2024
Would something like this work for you?
% CALCULATE MESHGRID
xa = linspace(-2,2,501) + 0.002;
ya = linspace(-2,2,501) + 0.002;
[X,Y] = meshgrid(xa,ya);
% CALCULATE Z
Z = 1./((X - 1).^2 + (Y - 1).^2) - 1./((X + 1).^2 + (Y + 1).^2) + 5*(cos(X)+sin(Y));
% SCALE Z
ZS = sign(Z).*abs(log10(Z));
surf(X,Y,ZS)
axis equal tight
shading interp
colorbar;
view([ 0 90 ])
3 Comments
See Also
Categories
Find more on Red in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!