How to make a a certain range with different color in colorbar

I created a a contour plot and I would like to make the range between -50 and 0 different than the range 0 and 50 as below. Anway to help please
[X,Y] = meshgrid(10:5:80,0:1:20);
Z = f([X(:), Y(:)]);
Z1 = reshape(Z,[21,15]);
figure
contour(X,Y,Z1,15000)
colormap hsv
colorbar
xlabel('\gamma (%)')
ylabel('\lambda (%)')
zlabel('m^{*}_{NPV} ($B)')

 채택된 답변

Sudheer Bhimireddy
Sudheer Bhimireddy 2020년 8월 8일

0 개 추천

댓글 수: 8

I would like to keep it as it is but I just want to hange these two ranges as i cant see the difference?
So you would like a color break at 0 in the same colormap to distinguish positive and negative transition?
Yes please, I'm happy with the colors except I cant tell the difference between -50 to 50
Option 1: If this is a one time thing you need, its easy to use:
colormapeditor
Option 2: You can get the colormap indices and map them to your array value range to edit the colors for respective values. Simple example would look something like this:
z = randi([-50 30],50,50);
h = figure(1);
cntr = contourf(z,'linecolor','none');
shading interp;
vmap = linspace(min(min(z)),max(max(z)),256);
cmap = hsv(256); % get the hsv colormap indices
cmap_0 = find(vmap>0,1,'first'); % find where your values become positive
cmap(cmap_0,:) = [1 1 1]; % You can create specific color at this location
cmap(cmap_0:end,3) = 0.6; % you can also change from there on
colormap(cmap);
c = colorbar;
caxis([min(min(z)) max(max(z))]);
Dear Sudheer, I have tried it and it is better but I have a problem to show the difference between 0 and 300 as below for option 2 and to show the variations between 0 and 5 in option 1 (anyway to fix this please). I have added my code and data as well.
Option 1:
Option 2
load('Penalty.mat')
load('table_summary.mat')
NPV = table_summary;
Demand = [5:5:95]';
x1 = repmat(Demand ,[1,length(NPV)]);
y1 = repmat(Penalty,[length(Demand),1]);
z1 = NPV;
y2 = [y1(:,1:11), y1(:,13:end)];
x2 = [x1(:,1:11), x1(:,13:end)];
z2 = [z1(:,1:11), z1(:,13:end)];
xx = x2(:);
yy = y2(:);
zz = z2(:);
f = fit([xx, yy],zz,'cubicinterp');
%%
[X,Y] = meshgrid(10:5:80,0:10);
Z = f([X(:), Y(:)]);
Z1 = reshape(Z,[11,15]);
figure
cntr = contourf(X,Y,Z1,'linecolor','none');
shading interp;
vmap = linspace(min(min(Z1)),max(max(Z1)),256);
cmap = hsv(256); % get the hsv colormap indices
cmap_0 = find(vmap>0,1,'first'); % find where your values become positive
cmap(cmap_0,:) = [1 1 1 1]; % You can create specific color at this location
cmap(cmap_0:end,3) = 0.6; % you can also change from there on
colormap(cmap);
c = colorbar;
%caxis([min(min(Z1)) max(max(Z1))]);
xlabel('\gamma (%)')
ylabel('p_{s}')
zlabel('m^{*}_{NPV} ($B)')
It is better but wanted to show how it vareis between 0 and 50.
First, your cmap array will be of size Nx3.
If I understand you correctly, you want to show the variation between 0 and 50, but not from 50 to 300.
If you have the indices for 0 and 50, you can edit the cmap array between the corresponding indices to show the variation and then can have same color for thereafter. Also know, that sometimes limiting the coloraxis (caxis([cmin cmax])) could be useful. If you want anyvalue after 50 to have the same color then caxis([min(z) 50]) will do the trick.
For Option 1, colormapeditor is a gui based method, so it is purely manual.
Thanks Sudheer, I want exactly what I have with additional variation between 0 and 50. The range is very small which I’m struggling to present.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Walter Roberson
Walter Roberson 2020년 8월 9일
The above function requires that the positions be defined in relative terms, 0 to 1, rather than in absolute terms. You would have to decide ahead of time what your caxis() is going to be, and use proportional positions through that range,
relative_position = (data_x - min_to_map)./(max_to_map - min_to_map)

댓글 수: 8

Thanks Walter but could not get what i wanted.
Create a vector containing all of the range boundaries that you want to distinguish. For example you might want [-100 -50 -25 -10 -5 0 5 10 25 50 100] in the case where fine differences near 0 were important to you.
diff() the boundary vector. Now find the gcd(), greatest common divisor https://www.mathworks.com/help/matlab/ref/gcd.html . This will be the size of one "slot" in the colormap, how quickly the colormap can switch between colors but without extra colormap entries. In the above example vector, the gcd would be 5. The size of the colormap you will generate will be (max(boundaries) - min(boundaries)) / gcd
Now take the difference vector divided by the gcd(). The result at each point is number of consecutive slots of the same color to use to represent that range. In the above example this would be 10 slots needed for the -100 to -50 range, 5 slots needed for the -50 to -25 range, 3 slots for -25 to -10, 1 slot for -10 to -5, -5 to 0, 0 to 5, 5 to 10, 3 for 10 to 25, 5 for 25 to 50, 10 for 50 to 100.
Take your color list, and repeat each entry the calculated number of times.
Now you can activate that colormap. And be sure to caxis() the entire range.
In theory you could take this approach right down to eps() difference between values. In practice, older versions of Windows only supported 256 colors; newer Windows 10 supports 65536 now.
... No, there is no way to just give a list of values representing boundaries, and corresponding colors, and have the graphics system work it all out; for it to do that, it would have to do the above kind of calculation, as the graphics standards such as OpenGL do not offer that facility.
Thanks Walter for all this. I have created my graph as below. However, not sure why my z-data or level data between 0 and 50 are not matching the colorbar. Do you think this is possible or I'm doing something wrong.
Could you post the relevant part of the code?
At the moment it looks to me as if you might have an off-by-one in the bins.
Dear Walter, here is my code and data as well. I'm trying to show everything including the variation between 0 and 50. I like this plot but i want to show how 0, 10, 20,...50 varry too. Thanks a lot for yur help
%%
load('New All NPV.mat')
Penalty = 0:.25:10;
NPV = table_summary;
Demand = [5:5:95]';
x1 = repmat(Demand ,[1,length(NPV)]);
y1 = repmat(Penalty,[length(Demand),1]);
z1 = NPV;
xx = x1(:);
yy = y1(:);
zz = z1(:);
f = fit([xx, yy],zz,'cubicinterp');
% estimate new points
[X,Y] = meshgrid(10:5:80,0:.25:10);
Z = f([X(:), Y(:)]);
Z1 = reshape(Z,size(X));
figure
[a,b] = contourf(X,Y,Z1);
clabel(a,b);
c = colorbar;
xlabel('\gamma (%)')
ylabel('p_{s}')
You posted a .xlsx but your code loads a .mat ?
Oh I’m sorry I just added the xsl for you since I though I can’t upload the mat file.
levels = [-700 -600 -500 -400 -300 -200 -100 -50 -40 -30 -20 -10 0 10 20 30 40 50 100 200 300];
[a,b] = contourf(X, Y, Z1, levels);
This will not in itself create new colormap entries for the various levels, but it will outline them more clearly.
To create new colormap entries, you have to follow the strategy I outlined above, of creating a colormap with replicated slots.

댓글을 달려면 로그인하십시오.

카테고리

도움말 센터File Exchange에서 Color and Styling에 대해 자세히 알아보기

태그

Community Treasure Hunt

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

Start Hunting!

Translated by