Personalized colormaps with thresholds and NaN
24 次查看(过去 30 天)
显示 更早的评论
Hello, I am trying to show the values of a 2D matrix called "2D" with the function "colormap(data)". But I would like to have a personnalized colormap. In particular I would like that: - All NaN values are shown in black - All values below 100 are shown in red - All values between 100 and the maximum are shown as a "hsv" gradient.
How can I achieve such a color map? I am basically stuck at the threshold + NaN values in black. I found a trick to have NaN values in black, but that trick doesn't allow me to have values <100 in a specified color.
Thank you in advance for your time and help.
Best, Julia
1 个评论
Adam
2017-7-24
It is achievable in a discretised manner, but is not trivial and I certainly don't have time at the moment to give enough details, but you would need to combine a custom colourmap and use of a manual caxis setting.
e.g. you can make the very first element of the colourmap black. this is the value NaNs will take. However, if your colourmap is e.g. length 256 it is also the colour that the bottom 1/256 of the values will take, so if your data ranges up to 25600 then everything up to 100 would take this value.
That is the problem with trying to create such a specific colourmap. Your data gets mapped from whatever its range is onto the discretised 256 values of the colourmap so unless your data range is e.g. 1-256 it is hard to achieve exact colour cutoff points for an arbitrary data range.
You can create a colourmap of greater size so potentially that is an option, but it depends again on your data range. If it is e.g. 1 to 1000 then you can easily create a colourmap of size 1000 (or 1001 to include special NaN handling), but if your range is up to e.g. 10,000 then a colourmap of that size is rather infeasible and way beyond what the human eye can distinguish.
To separate the NaNs out you need to ensure that the lowest value in your data will map to the start of the 2nd bin in the colourmap. This may well require you to change your actual data to avoid having some of it fall into the first (NaN) bin.
回答(2 个)
Chad Greene
2017-7-24
编辑:Chad Greene
2017-7-24
You can make the NaNs transparent and make the background axes black like this:
% A sample matrix:
Z = 75*peaks(5)+100;
% with NaNs in it:
Z([3 4 25]) = nan;
% Display the matrix as color-scaled image:
h = imagesc(Z);
% Set nan values to transparent:
set(h,'alphadata',~isnan(Z))
% Make the background black:
set(gca,'color','black')
% Add a colorbar:
colorbar
% Set color axis limits:
caxis([100 700])
% Set the colormap to hsv:
colormap(hsv(256))
And any values under 100 will have the color corresponding to the lowest value in the colormap.
3 个评论
Yogesh Kumkar
2022-3-4
Thanks. I am using the same but for subplots.
In my case, it does not work. The plots shows wrong colors.
width=800; height=800; x0=10; y0=10;
cx = [min([dLST_JJA_I(:) dLST_SON_I(:) dLST_DJF_I(:) dLST_MAM_I(:)]), max([dLST_JJA_I(:) dLST_SON_I(:) dLST_DJF_I(:) dLST_MAM_I(:)])];
cMin = min(cx(:)); cMax = max(cx(:));
figure(1)
set(gcf,'units','points','position',[x0,y0,width,height])
%$*********************** LST ***********************$%
ax11=subplot(2,2,1);
h1=imagesc(rot90(dLST_JJA_I));axis on;grid;
set(h1,'alphadata',~isnan(rot90(dLST_JJA_I))); % this is better than cmap11(1,:) = [0.5 0.5 0.5];
cmap11=colormap(ax11,bluewhitered(256));
% cmap11(1,:) = [0.5 0.5 0.5];
set(gca,'color', [0.5 0.5 0.5])
colorbar; caxis([cMin cMin]);
%cmap11=colormap(ax11,bluewhitered);
%cmap11(1,:) = [0.5 0.5 0.5];
%colormap(ax11,cmap11);
%clims11 = get(ax11, 'CLim');
%ax11.CLim = [cMin cMax];
Please suggest. Thanks.
Jimmy Zhang
2023-2-1
Found a way to solve this problem by breaking down the function "imagesc" to rescale, ind2rgb, image. The result is slightly different from that of imagesc, which I think comes from the unknown process of boundary value handeling in ind2rgb. I don't want to dig more into the built-in function of matlab and find where the difference comes out and I think the solution below already solves this problem. Hope this help you too.
% Generate whatever sample
D = rand(100)*1000;
D([400:500]) = nan;
figure, imagesc(D);
% Convert raw data to rgb image
cmap = jet(); % arbitary colormap
I = double(D);
I = rescale(I, 0, 256);
I = ceil(I);
I = ind2rgb(I, cmap);
% Handle nan value
colorToChange = [1, 1, 1]; % arbitary color in RGB
colorToChange = reshape(colorToChange, 1, 1, 3);
colorMask = isnan(D) | D<100;
I = I .* ~colorMask; % make sure your matlab version is new enough for dimension broadcasting, or handle it mannually
I = I + colorMask .* colorToChange;
% Display
figure, image(I);
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Orange 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!