I want to make a colormap including three ticklabels: Low, Intermediate and High. However, these labels should correspond to a range of values. Low = 0-50, Intermediate = 50-100 and High = 100 - maxvalue.
The code I have so far is written below, however it goes wrong when I want to define the Ticks. Could someone help me how to implement the ranges in to the ticks?
Thanks a lot!
figure, imshow(result);
[maxval] = max(result(:));
[minval] = min(result(:));
% red, yellow, green
cmap = [0 1 0; 1 1 0; 1 0 0];
colormap(cmap);
h = colorbar;
caxis([minval maxval]);
set(h, 'Ticks',[0:1:50, 50:1:100, 100:1:maxval])
set(h,'Ticklabels',{'Low','Intermediate','High'})
Rather than you colormap only having three values, you'll want to repeat each value in your colormap several times so that it covers the whole range.
Also, you have defined your ticks to be an array of many arrays (0:1:50 creates an array of 50 values). Each value in the array used for the 'Tick' property is a separate tick.
Instead of passing in arrays, you'll want to take the mean of each range and use that as the tick location.
Something like this should accomplish what you want.
crange = 0:maxval;
cmap = zeros(numel(crange), 3);
cmap(:,1) = crange >= 50;
cmap(:,2) = crange < 100;
colormap(cmap);
h = colorbar;
caxis([0 maxval]);
set(h, 'Ticks', [25 75 mean([100 maxval])], ...
'TickLabels', {'Low', 'Intermediate', 'High'});
Related
This should be simple, but I'm having trouble getting the scaling of a custom color map to match the range of values that I'm plotting. I don't quite understand how to get the range on the colorbar to match the range of the Z-dimension data. Here's a simple example that I'm trying to get working:
maxval = 5;
num = 10;
X = linspace(0,maxval,num);
Y = linspace(0,maxval,num);
Z = linspace(0,maxval,num);
cMap = interp1([0;1],[1 .5 0; .5 1 0],linspace(0,1,num));
scatter3(X,Y,Z,50,cMap,'Filled');
view(-75,20);
colormap(cMap)
colorbar
Which gives this:
I want the top value in the colorbar to be 5 in this example. I've tried modifying the [0;1] in the interp1 function, but I can't seem to get the correct settings.
I'm using version 2017a, if that matters.
The 5th input in scatter3 can represent a completely independent axis of data. If you want the color to match the Z axis data, then you need to pass it in twice.
The custom colormap (which can be a different size than the data) in interpolated to this 5th input to make the display.
Pragmatically, I think you want to make the following change to your code:
maxval = 5;
num = 10;
X = linspace(0,maxval,num);
Y = linspace(0,maxval,num);
Z = linspace(0,maxval,num);
cMap = interp1([0;1],[1 .5 0; .5 1 0],linspace(0,1,num));
scatter3(X,Y,Z,50,Z,'Filled'); % <-- note change here
view(-75,20);
colormap(cMap)
colorbar
Question: How do I specify color transitions in a custom MATLAB colorbar?
Specifically, I'd like to make the yellow (see below) cover more area of the colorbar (perhaps [19.5–21.5] or something close to that).
Using this answer, I was able to create a custom colorbar in MATLAB. I'm trying to understand this answer as it might be relevant.
I have attempted approaches from this answer and reviewed this answer & this one and was unable to accomplish my goal.
It is clear I am missing something.
Full representative example below
% MATLAB 2017a
% Data
X = [22.6 22.8 22.6 20.45 22.3 18.15 19.95 20.8].';
Y = [84 89 63 81 68 83 77 52].';
Z = [23.0 22.695 21.1450 21.5 22.09 20.5 22.075 20.915].';
% Create custom colormap
% Reference: https://stackoverflow.com/questions/24488378/how-to-map-a-specific-value-into-rgb-color-code-in-matlab/24488819#24488819
col3 = [0 1 0]; %G
col2 = [1 1 0]; %Y
col1 = [1 0 0]; %R
n1 = 20; n2 = 20;
cmap=[linspace(col1(1),col2(1),n1);linspace(col1(2),col2(2),n1);linspace(col1(3),col2(3),n1)];
cmap(:,end+1:end+n2)=[linspace(col2(1),col3(1),n2);linspace(col2(2),col3(2),n2);linspace(col2(3),col3(3),n2)];
cmap = cmap.';
% Plot
colormap(cmap), hold on, box on
p = scatter(X,Y,[],Z,'filled','DisplayName','Data3');
cb = colorbar;
cb.Limits = [18 23];
cb.Ticks = [18:1:23];
% Cosmetics
p.MarkerEdgeColor = 'k';
xlabel('X')
ylabel('Y')
cb.Label.String = 'Z';
I think all that you're missing is a call to caxis to specify the minimum and maximum values to map the color range to:
caxis([18 23]);
Note that the following line...
cb.Limits = [18 23];
... only changes the tick limits displayed on the colorbar, but doesn't change anything about how the data is mapped to the color range. The caxis function is how you control that (in the above case, mapping the value of 18 to one end and the value of 23 to the other). By default, your code was mapping the minimum and maximum values in Z to the color range (20.5 and 23, respectively). When you then set the tick limits on the color bar to a larger range, it just filled it in with the last color in the color map, in this case red. That's why you see so much of it.
Bonus
Just because you might be interested, you could also use interpolation via the interp1 function to easily generate your color map like so:
cmap = interp1([1 0 0; 1 1 0; 0 1 0], linspace(1, 3, 41));
This question is following on from a previous question about HSV color space.
Let's say I have two arrays A and B, where A are my data points (2D) of interest to be shown in the colorbar and B is an RGB image transformed from the HSV color space where: Hue is in the interval [0.25-1] (corresponding to normalized A values 0.25-1), Saturation = 1, Value in interval [0-1] (corresponding to some other values).
When displaying B with imshow, I want to create a matching colorbar with ticks that correspond to the value range from A.
First difficulty that I'm facing is that I want my Hue to be in the interval [0.25-1] and hence I only need a certain part of the hsv colorbar to be displayed.
Second difficulty is that I need to match the value range from A to the colorbar.
Example code:
A = rand(30,30)*0.4; % Values range from 0 - 0.4
X = rand(30,30)*100+100; % Values range from 100 - 200
A_n = A / (max(A(:))/0.75) + 0.25; % "Normalize", with range 0.25 - 1
X_n = X / max(X(:)); % Normalize, range 0 - 1
colorRGB = NaN([size(A),3]); % preallocate
for ii = 1:size(A,1)
for jj = 1:size(A,2)
colorRGB(ii,jj,:) = hsv2rgb([A_n(ii,jj),1,X_n(ii,jj)]); % turn into RGB
end
end
imshow(colorRGB), % display image
colormap hsv; cb = colorbar();
In the example you can see that the colourbar covers the whole hsv range and has ticks from 0 - 1.
What I want it to be is showing only the upper 75% of the hsv range with ticks from 0 to max(A(:))
The correct colorbar assuming that max(A(:)) = 0.35 should look like this:
(you can see that I just cropped it, but that should not be necessary either)
In order to do that you need 2 things. First crop the colorbar, bu setting its limits. Secondly, change the text in the labels of the colobar, but to make sure they are in the rigth places, you also need to set the positions of them manually. Hopefully the code makes sense:
cb = colorbar();
set(cb, 'ylim', [25 100])
set(cb, 'XTick', [25:15:100]) % modify values if you preffer
set(cb,'XTickLabel',strsplit(num2str([0.25:0.15:1])));
just want to check if it is possible to make a custom colormap with only 3 colors? (there is no need for gradient).
Example: Data ranges from 0-100,
so 0-33 is one color,
34-67 is another color,
and 68-100 is another color.
Just use a colormap with three rows. Each row defines a color in terms of R, G, B components.
A = randi(100,16,16); %// example data
imagesc(A) %// display matrix as image
colormap([1 0 0; 0 1 0; 0 0 1]) %// apply colormap
colorbar %// show color bar
This defines uniformly spaced thresholds between colors. If you need more control you need to have more than three rows, with some of the colors repeated. For example,
colormap([1 0 0; 1 0 0; 0 1 0; 0 0 1]) %// apply colormap
will define a 50% threshold for first color, 75% for second and 100% for third.
Take this example:
% some matrix with integer values in the range [0,100]
Z = peaks;
Z(:) = round((Z(:)-min(Z(:))) ./ range(Z(:))*100);
% show as image (with scaled color mapping)
image(Z, 'CDataMapping','scaled')
caxis([0 100]) % set axes CLim property
colormap(eye(3)) % set figure Colormap property
colorbar % show colorbar
Note that the colors are scaled to the range [0 100], that range is mapped to the current figure's colormap (which we set to only three colors).
Follow this example: How to create a custom colormap programmatically? but instead of R = linspace(0,t(1),50)' you would use R = ones(50,1)*t(1)
or even simpler:
if colour 1 is t1 = [r1, g1, b1] etc then
map(1:34, :) = repmat(t1, 33, 1)
map(35:68, :) = repmat(t2, (67-34), 1)
etc...
OR
map(1:34, :) = bsxfun(#times, t, ones(33,3))
etc...
Check my answer here
You can use that code and decide to interpolate between values or not, its just 2 lines of the code.
The result image shown in the original post for a GYR cutom colormap.
I'd like to have a surface plot like the one below, but with a proper 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.
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.
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));
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]);
So after all, I think my first method (using yticklabels) is the only way of doing what you want.
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.
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