필터 지우기
필터 지우기

Personalized colormaps with thresholds and NaN

조회 수: 40 (최근 30일)
Julia
Julia 2017년 7월 24일
답변: Jimmy Zhang 2023년 2월 1일
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
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
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
Hoyoung Jang
Hoyoung Jang 2021년 1월 14일
Very helpful.Thanks.
Yogesh Kumkar
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
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);

카테고리

Help CenterFile Exchange에서 Blue에 대해 자세히 알아보기

태그

Community Treasure Hunt

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

Start Hunting!

Translated by