jhscheer
jhscheer

Reputation: 351

How to combine a custom color range with colorbar in MATLAB?

I'd like to have a surface plot like the one below, but with a proper colorbar.

plot without colorbar

This is my code:

[X,Y,Z] = peaks(30);

[maxval dummy] = max(Z(:));
[minval dummy] = min(Z(:));

crange = 1.5;

% red, yellow, green
cmap = [1 0 0; 1 1 0; 0 1 0];  
colormap(cmap); 

colors = zeros(size(Z));                   
colors(Z <= -crange) = 1;              % red (1)
colors(Z > -crange & Z < crange) = 2;  % yellow (2)
colors(Z >= crange) = 3;               % green (3)

surf(X,Y,Z, colors);
axis([-3 3 -3 3 -10 10]);

%cbh = colorbar('YGrid','on');    
%caxis([minval-0.1 maxval+0.1]);
%set(cbh,'YTick',[minval -crange crange maxval]);

So far I had no luck in adding a colorbar where the colors (green,yellow,red) are aligned according to my custom range (green[8 ... 1.5],yellow[1.5 ... -1.5], red[-1.5 ... -6.4]). Instead, when I uncomment the last three lines, a colorbar with linearly aligned colors shows up and the colors in my plot are aligned according to the colorbar and not to my custom range.

plot with colorbar

Now, what I'd like to have is that the colors in the colorbar match my custom ticks and that the plot looks like in the first picture.

Upvotes: 3

Views: 14110

Answers (3)

Nilanthi
Nilanthi

Reputation: 1

I came across this question when finding solutions for a problem that I had. Anyway this question helped me to get a solution for my problem after making little modifications on written codes. At the same time I like to suggest some changes for the code so that user can get the required plot with necessary colors and the appropriate color bar also. Here is the code,

[X,Y,Z] = peaks(30);

[maxval dummy] = max(Z(:));
[minval dummy] = min(Z(:));

crange=1.5;

% red, yellow, green
cmap = [1 0 0; 1 1 0; 0 1 0];  
colormap(cmap); 

colors = zeros(size(Z));                   
colors(Z <= -crange) = minval-0.1;              % red (1)
colors(Z > -crange & Z < crange) = crange;  % yellow (2)
colors(Z >= crange) = maxval+0.1;              % green (3)

surf(X,Y,Z, colors);
axis([-3 3 -3 3 -10 10]);

cbh = colorbar('YGrid','on');    
caxis([minval-0.1 maxval+0.1]);
set(cbh,'YTick',[minval -crange crange maxval]);

Plot

Upvotes: 0

Ben
Ben

Reputation: 329

I know this is a crazy old post, but it came up as I was looking for answers. And here would be my answer (which has to assume unfortunately that the graduations on the color bar are equal size).

So given that you have made the color map, which is only 3 colors, the next part is algebra. The caxis follows a simple formula which is determined by the how many colors are in the color bar, and your min and max range.

index = fix((C-cmin)/(cmax-cmin)*m)+1;

So index will refer to the index in the color map (m = 3 since that is the length of your colormap), and what I would do is make C= 1.5, decide if you want it symmetrical (you are solving for cmax and cmin and is easier if both are x), and make index=2 (since you only have 3 colors, that should mean solving for 1.5 would give you the cmin/cmax to set which would make 1.5 the cutoff between yellow and red. You should be able to set the display range value somewhere, which will set the colormap appropriately (though probably not the labels).

Sorry to reply to such an old post, but maybe this will help others.

Upvotes: 1

Gunther Struyf
Gunther Struyf

Reputation: 11168

The problem is that you specify the colors of each point in the surf plot by yourself, so they're not related to the z-value as is by default. The colorbar therefor is constructed only based on the color numbers, being 1 to 3. These therefor also show up as the default ticks of the colorbar (before you change them.

As you found out, you can set the ticks manually, and in the same way you can 'cheat' and use yticklabels:

figure
colormap(cmap); 
surf(X,Y,Z, colors);
axis([-3 3 -3 3 -10 10]);

cbh = colorbar('YGrid','on');
set(cbh,'ytick',linspace(1,3,4));
set(cbh,'yticklabel',arrayfun(@num2str,[minval -crange crange maxval],'uni',false));

enter image description here

Or another way is to simply use caxis, but then the colors of the plot are linearly defined by the minmax values. So with this you can't set your non-linear ranges.
Illustration:

figure
colormap(cmap); 
surf(X,Y,Z);
axis([-3 3 -3 3 -10 10]);
caxis([minval-0.1 maxval+0.1]);
cbh=colorbar
set(cbh,'YTick',[minval -crange crange maxval]);

enter image description here

So after all, I think my first method (using yticklabels) is the only way of doing what you want.

Upvotes: 4

Related Questions