# Define vector to use for colorbar

84 views (last 30 days)
Joel on 8 Nov 2016
Commented: Joel on 14 Nov 2016
Hi,
I am plotting a bar+scatter plot where the scatter points are colored according to a separate variable. The problem I am having is that the colorbar is, for some reason that is beyond me, using the wrong values at the moment. If I just plot the scatter plot and add a colorbar, then the range of the colorbar is correct. I have been trying every solution I can come up with, but have not made any progress. Any help would be very much appreciated. Please find a working example of the code below;
figure
subplot(2,1,1)
a = 1;
b = 2;
r = (b-a).*rand(1,7) + a;
y = r;
rr = (b-a).*rand(1,7) + a;
z = rr;
x = [1:7];
zz = rand(1,7)
yyaxis left
hold on
for i = 1:7
h=bar(i,y(i), 'FaceColor',[1 1 1], 'LineWidth',3);
yb(i) = cat(1, h.YData);
xb(i) = bsxfun(@plus, h(1).XData, [h.XOffset]');
if zz(i) < 0.0300000
set(h,'EdgeColor','k');
elseif zz(i) < 0.050000000
set(h,'EdgeColor','b');
elseif zz(i) < 0.070000000
set(h,'EdgeColor','g');
else
set(h,'EdgeColor','r');
end
end
ylabel('hm', 'FontSize', 12, 'FontWeight', 'bold')
for i1=1:7
t = text(xb(i1)-0.2,yb(i1),num2str(yb(i1),'%0.3f'),...
'HorizontalAlignment','center',...
'VerticalAlignment','bottom')
s = t.FontSize;
t.FontSize = 12;
t.FontWeight = 'bold';
end
yyaxis right
pointsize = 40;
hh = scatter(x,z,pointsize, zz,'filled')
cc = colormap([hsv(20)])
c = colorbar
c.Label.String = 'Pos';
set(gca,'Ydir','reverse')
ylabel('OK', 'FontSize', 12, 'FontWeight', 'bold')
lgd = legend([h, hh], 'hm', 'OK')
subplot(2,1,2)
x = [1:8]
a = 1;
b = 2;
r = (b-a).*rand(1,8) + a;
y = r;
rr = (b-a).*rand(1,8) + a;
z = rr;
zz = rand(1,8);
yyaxis left
hold on
for i = 1:8
h=bar(i,y(i), 'FaceColor',[1 1 1], 'LineWidth',3);
yb(i) = cat(1, h.YData);
xb(i) = bsxfun(@plus, h(1).XData, [h.XOffset]');
if zz(i) < 0.0300000
set(h,'EdgeColor','k');
elseif zz(i) < 0.050000000
set(h,'EdgeColor','b');
elseif zz(i) < 0.070000000
set(h,'EdgeColor','g');
else
set(h,'EdgeColor','r');
end
end
for i1=1:8
t = text(xb(i1)-0.2,yb(i1),num2str(yb(i1),'%0.3f'),...
'HorizontalAlignment','center',...
'VerticalAlignment','bottom')
s = t.FontSize;
t.FontSize = 12;
t.FontWeight = 'bold';
end
ylabel('hm', 'FontSize', 12, 'FontWeight', 'bold')
yyaxis right
pointsize = 40;
hh = scatter(x,z,pointsize, zz,'filled')
set(gca,'Ydir','reverse')
ylabel('OK', 'FontSize', 12, 'FontWeight', 'bold')
c = colorbar
c.Label.String = 'Pos';
lgd = legend([h, hh], 'hm', 'OK')
%title(lgd,'My Legend Title')
hold off
Thanks in anticipation.
Regards Joel

Nick Counts on 9 Nov 2016
Ok, I spend some time with this and I think i see what's happening. It all boils down to the way you define the CData property of your scatter plot. Here is a simple example that should illustrate how it works:
xData = 1:10
yData = rand(1, 10) + 1 % random number between 1 and 2
cVect = yData;
colormap(jet(10));
hScat = scatter(xData, yData, 100, cVect, 'Filled')
hcbar = colorbar
caxis([1 2])
This sets the CData to the same value as the yData vector, and then we use caxis to determine the boundaries of the displayed color scale.
Now in your code, it looks like you are using the variable zz as your CData value in your scatter plot. You define it this way:
zz = rand(1,7)
This means it will be a 7 element vector with values between 0 and 1. When you use colormap you are creating an array of colors that your CData will be mapped to. Without specifying a caxis, I think Matlab automatically maps the bottom color to the lowest CData value, and the top color to the highest CData value.
From your code, I assume you want to map a zz value of 0 to the bottom color, and a zz value of 1 to the top color?
If so, the following simplification of your example should do the trick:
figure
% Generate Data
a = 1;
b = 2;
r = (b-a).*rand(1,7) + a;
y = r;
rr = (b-a).*rand(1,7) + a;
z = rr;
x = [1:7];
zz = rand(1,7)
% yyaxis left % Removed because I'm on 2014b
% Draw rectangles
hold on
for i = 1:7
hBarGraph = bar(i,y(i), 'FaceColor',[1 1 1], 'LineWidth',3);
yb(i) = cat(1, hBarGraph.YData);
xb(i) = bsxfun(@plus, hBarGraph(1).XData, [hBarGraph.XOffset]');
if zz(i) < 0.0300000
set(hBarGraph,'EdgeColor','k');
elseif zz(i) < 0.050000000
set(hBarGraph,'EdgeColor','b');
elseif zz(i) < 0.070000000
set(hBarGraph,'EdgeColor','g');
else
set(hBarGraph,'EdgeColor','r');
end
end
ylabel('hm', 'FontSize', 12, 'FontWeight', 'bold')
% Text labels for rectangles
for i1=1:7
t = text(xb(i1)-0.2,yb(i1),num2str(yb(i1),'%0.3f'),...
'HorizontalAlignment', 'center',...
'VerticalAlignment', 'bottom');
t.FontSize = 12;
t.FontWeight = 'bold';
end
% yyaxis right % Removed because I'm on 2014b
% Scatter Plot
pointsize = 40;
hAxes = gca;
colormap(hsv(20))
colorBounds = [0 1];
caxis(colorBounds)
colorbar
hScatterPlot = scatter(x,z,pointsize, zz,'filled')
set(hAxes,'Ydir','reverse')
ylabel('OK', 'FontSize', 12, 'FontWeight', 'bold')
lgd = legend([hBarGraph, hScatterPlot], 'hm', 'OK')
If this doesn't help, please let us know more about what color behavior you want. Good luck, and let us know how it goes! :)
Joel on 14 Nov 2016
Thank you, Nick! I really appreciate you taking the time!
Your solution is even better than what I had in mind. Initially I just wanted the colorbar to be governed by the third variable, zz, in the scatter plot. I failed with this, as the range of the colorbar was not the same as the range of the zz variable. And if I forced the colorbar to be the same range, the color of the colorbar did not match the scatter plot.
I found a way to solve this - however, your code is, a mentioned, much better! Thank you again!
I will attach my code just to show how I did it;
figure
a = 1;
b = 2;
r = (b-a).*rand(1,7) + a;
y = r;
rr = (b-a).*rand(1,7) + a;
z = rr;
x = [1:7];
zz = rand(1,7)
colormap(jet)
yyaxis left
hold on
for i = 1:length(y)
h=bar(i,y(i), 'FaceColor',[1 1 1], 'LineWidth',3);
yb(i) = cat(1, h.YData);
xb(i) = bsxfun(@plus, h(1).XData, [h.XOffset]');
if zz(i) < 0.0300000
set(h,'EdgeColor','k');
elseif zz(i) < 0.050000000
set(h,'EdgeColor','k');
elseif zz(i) < 0.070000000
set(h,'EdgeColor','k');
else
set(h,'EdgeColor','k');
end
end
cco = min(zz)
cct = max(zz)
caxis([cco cct])
coloo = colorbar
coloo.Label.String = 'Cbar';
%h = bar(y, 0.2, 'FaceColor',[1 1 1], 'EdgeColor',[0 0 0],'LineWidth',2);
%yb = cat(1, h.YData);
%xb = bsxfun(@plus, h(1).XData, [h.XOffset]');
for i1=1:7 % numel(yb)
t = text(xb(i1)-0.3,yb(i1),num2str(yb(i1),'%0.3f'),...
'HorizontalAlignment','center',...
'VerticalAlignment','bottom')
s = t.FontSize;
t.FontSize = 12;
t.FontWeight = 'bold';
end
ylabel('OK', 'FontSize', 12, 'FontWeight', 'bold')
yyaxis right
pointsize = 80;
hh = scatter(x,z,pointsize, zz,'filled')
set(gca,'Ydir','reverse')
ylabel('MM', 'FontSize', 12, 'FontWeight', 'bold')
c = colorbar
c.Label.String = 'Cbar';
lgd = legend([h, hh], 'OK', 'MM')
%title(lgd,'My Legend Title')
hold off

Nick Counts on 8 Nov 2016
Edited: Nick Counts on 8 Nov 2016
Joel,
I don't know about a vector, but you can set upper and lower limits. It looks like you are saving a handle to the colorbar in variable 'c'
Try:
c.Limits = [0 10]
Obviously use whatever numbers make sense for your plots :)
Good luck!
Joel on 8 Nov 2016
Thank you, Nick!
Whilst I've still not solved the question, I've narrowed down the source of the error.
If I use
caxis
to print out the values of caxis they look just like they should. The lower and upper limits are what they should be.
However, the colorbar is still not synchronized with caxis, for some reason. The original range of the colorbar i between 1 and 2.
If I change this using the following code,
c = colorbar
cc = caxis
c.Limits = [cc(1) cc(2)]
The resulting colorbar is simply a capped version of the previous colorbar. That is, the full color-range is not present - the color-range is what c.Limits would have been before. For example, if my original colorbar is between red and blue, the new colorbar is just red. It is tricky to explain, but I hope I make some sense.
Regards Joel