Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Contrasting color for NaNs in imagesc

Tags:

matlab

I fill unused elements in a matrix with NaNs, and I would like to assign a contrasting color to those elements with the NaN value when displaying the data using imagesc.

Below is a link to a possible solution, but I don't quite understand it.

http://www.mathworks.com/matlabcentral/newsreader/view_thread/19985

like image 421
flamearchon Avatar asked Dec 12 '11 21:12

flamearchon


3 Answers

NaN values get the first color from the axes colormap, which by default corresponds to the minimum value (other than NaN). You can change the color for minimum value setting axes color limits with CAXIS function. To assign a contrast color to NaN values you can add a special color for NaN values as a first color (1x3 vector).

I take your example and made a function (with some comments):

function [h hcb] = imagescwithnan(a,cm,nanclr)
% IMAGESC with NaNs assigning a specific color to NaNs

%# find minimum and maximum
amin=min(a(:));
amax=max(a(:));
%# size of colormap
n = size(cm,1);
%# color step
dmap=(amax-amin)/n;

%# standard imagesc
him = imagesc(a);
%# add nan color to colormap
colormap([nanclr; cm]);
%# changing color limits
caxis([amin-dmap amax]);
%# place a colorbar
hcb = colorbar;
%# change Y limit for colorbar to avoid showing NaN color
ylim(hcb,[amin amax])

if nargout > 0
    h = him;
end

Here caxis statement assigns the first color of the color map not to the minimum value amin, but to the amin-dmap. So the first color get assigned specifically to NaNs.


Try this function with:

a=peaks;
a(a < 0.5) = nan;
imagescwithnan(a,hot,[0 1 1]) %# [0 1 1] is cyan

test image - NaN color is hidden

If you comment the ylim statement in the function (can be control with additional parameter) this NaN color will be on the colormap.

test image - NaN color is shown on the colorbar

like image 129
yuk Avatar answered Oct 04 '22 04:10

yuk


There are 2 general steps to using multiple color maps like this:

  1. Stack the new colormap with your old one.
  2. Shift the new values that you want to map to this new colormap so that the ratio of range(new data) to range(old data) is the same as nrow(new colormap) to nrow(old colormap).

This will successfully map the new data to the new colormap, while at the same time mapping the old data to the old colormap (i.e. not altering the colors of the old data). Also note that a copy of the data gets stored with the image, so we can do this shifting without altering the original values.

A simplified example:

% Make image data
img = -5:5;

% Plot with original colormap
figure
imagesc(img);
colormap(hot(8))

% Add in an NaN
img(3) = NaN;

% Make new colormap
n = 8;
cols = [0 0 1 %blue
        hot(n)];

% Plot with new colormap
figure
h = imagesc(img);
colormap([0 0 1; hot(8)])

% Scale data so that the range proportions match the colormap sizes
cdata = get(h, 'CData');
img_range = range(cdata(:));
cdata(isnan(cdata)) = min(cdata(:)) - img_range/n;
set(h, 'CData', cdata);

enter image description here

enter image description here

like image 23
John Colby Avatar answered Oct 04 '22 03:10

John Colby


This question shows up first in my search engine, but I found a much more preferable answer in this post so I thought I would include it here.

In summary, use the following:

imagesc(Z,'AlphaData',~isnan(Z))

Alternatively, note that pcolor ignores nans by default.

like image 30
dkv Avatar answered Oct 04 '22 03:10

dkv