How to add a color-dependent legend to scatter3 plot?

13 views (last 30 days)
I have a 3D histogram via scatter3, but I wish to add a legend to state the frequency signified by the color. How do I do this?
Also, I would appreciate any simplifications you could suggest to my code below.
%%Plot a scatter3 histogram of the shifts.
xdata = tumorshifts(:,1); ydata = tumorshifts(:,2);
zdata = tumorshifts(:,3);
size = 10*shiftno;
for loop = 1:length(size)
if isequal(shiftno(loop),1)
size(loop) = size(loop)/10;
end
end
color = zeros(length(shiftno),3);
values = unique(shiftno);
% Resource: http://www.wolframalpha.com/input/?i=orange+RGB
% http://www.wolframalpha.com/input/?i=576+nm+light+to+RGB
for loop = 1:length(color)
if shiftno(loop) == values(1)
color(loop,1) = 130; color(loop,2) = 130; color(loop,3) = 130; % grey
elseif shiftno(loop) == values(2)
color(loop,1) = 41; color(loop,2) = 0; color(loop,3) = 255; % 452 nm
elseif shiftno(loop) == values(3)
color(loop,1) = 0; color(loop,2) = 214; color(loop,3) = 69; % 514 nm
elseif shiftno(loop) == values(4)
color(loop,1) = 132; color(loop,2) = 252; color(loop,3) = 0; % 576 nm
elseif shiftno(loop) == values(5)
color(loop,1) = 255; color(loop,2) = 8; color(loop,3) = 0; % 638 nm
elseif shiftno(loop) == values(6)
color(loop,1) = 158; color(loop,2) = 0; color(loop,3) = 0; % crimson
end
end
scatter3(xdata,ydata,zdata,size,color/255)
axis equal
title(['Histogram of ',num2str(length(unique(elektapatients.StudyID))),...
' Elekta Patients'' Daily Shifts'])
xlabel('Left [mm]')
ylabel('Superior [mm]')
zlabel('Posterior [mm]')

Accepted Answer

Walter Roberson
Walter Roberson on 4 Aug 2016
%%Plot a scatter3 histogram of the shifts.
xdata = tumorshifts(:,1); ydata = tumorshifts(:,2);
zdata = tumorshifts(:,3);
pointsize = 10*shiftno;
for loop = 1:length(pointsize)
if shiftno(loop) == 1
pointsize(loop) = pointsize(loop)/10;
end
end
color = zeros(length(shiftno),3);
values = unique(shiftno);
% Resource: http://www.wolframalpha.com/input/?i=orange+RGB
% http://www.wolframalpha.com/input/?i=576+nm+light+to+RGB
cmap = [130, 130, 130; %grey
41, 0, 255; %452 nm
0, 214, 69; %514 nm
132, 252, 0; %576 nm
255, 8, 0; %638 nm
158, 0, 0]; %crimson
for loop = 1:length(color)
switch shiftno(loop)
case values(1): color(loop, :) = cmap(1,:); % grey
case values(2): color(loop, :) = cmap(2,:); % 452 nm
case values(3): color(loop, :) = cmap(3,:); % 514 nm
case values(4): color(loop, :) = cmap(4,:); % 576 nm
case values(5): color(loop, :) = cmap(5,:); % 638 nm
case values(6): color(loop, :) = cmap(6,:); % crimson
end
end
scatter3(xdata, ydata, zdata, pointsize, color/255)
axis equal
title(['Histogram of ', num2str(length(unique(elektapatients.StudyID))),...
' Elekta Patients'' Daily Shifts'])
xlabel('Left [mm]')
ylabel('Superior [mm]')
zlabel('Posterior [mm]')
hold on
for K = 1 : size(cmap, 1)
H(K) = scatter3(nan, nan, nan, K*10, cmap(K,:));
end
legend(H, {'grey', '452 nm', '514 nm', '576 nm', '638 nm', 'crimson'});
Note that size had to be renamed because you need the MATLAB size() function later.
Going from if/elseif to switch/case was just for cleaner code.
You might want to adjust the point size for the legend purposes.
Notice the trick here of using nan to create scatter points that will not show up. The points will exist and will have the proper color but they will not be rendered. This is done in order to get the individual handles of those scatter plots so that they can have individual legends generated. Any one scatter3() plot results in a single graphics handle and that would only permit a single legend entry. You need to create different handles for each entry you want to make.
  2 Comments
Daniel Bridges
Daniel Bridges on 8 Aug 2016
Edited: Daniel Bridges on 8 Aug 2016
What are the differences between isequal and == ?
This comment from doc isequal makes me think == additionally compares handles, making me think isequal is executed more quickly: "When comparing handle objects, use == to test whether objects have the same handle. Use isequal to determine if objects with different handles have equal property values."
MATLAB R2016a doesn't allow this use of : to put the statement on the same line as the case expression: "Error: The expression to the left of the equals sign is not a valid target for an assignment." (It is red-underlining the equals sign between color and cmap in the Editor. Erasing the colon and putting the statement in the following line resolves it.) Thank you for clarifying the logic of switch/case usage.
Here is the result with the new code:
%%Plot a scatter3 histogram of the shifts.
xdata = tumorshifts(:,1); ydata = tumorshifts(:,2);
zdata = tumorshifts(:,3);
pointsize = 10*shiftno;
for loop = 1:length(pointsize)
if isequal(shiftno(loop),1)
pointsize(loop) = pointsize(loop)/10;
end
end
color = zeros(length(shiftno),3);
values = unique(shiftno);
% Resource: http://www.wolframalpha.com/input/?i=orange+RGB
% http://www.wolframalpha.com/input/?i=576+nm+light+to+RGB
cmap = [130, 130, 130; % grey
0, 255, 0; % 545 nm lime green
41, 0, 104; % 390 nm dark purple
255, 113, 0; % 623 nm orange
0, 54, 249; % 468 nm deep blue
158, 0, 0]; % 700 nm crimson
for loop = 1:length(color)
switch shiftno(loop)
case values(1)
color(loop,:) = cmap(1,:); % grey
case values(2)
color(loop,:) = cmap(2,:); % 452 nm
case values(3)
color(loop,:) = cmap(3,:); % 514 nm
case values(4)
color(loop,:) = cmap(4,:); % 576 nm
case values(5)
color(loop,:) = cmap(5,:); % 638 nm
case values(6)
color(loop,:) = cmap(6,:); % crimson
end
end
scatter3(xdata,ydata,zdata,pointsize,color/255)
axis equal
title(['Histogram of ',num2str(length(unique(elektapatients.StudyID))),...
' Elekta Patients'' Daily Shifts'])
xlabel('Left [mm]')
ylabel('Superior [mm]')
zlabel('Posterior [mm]')
%%add a legend to the scatter3 histogram
hold on
for loop = 1:size(cmap,1)
VectorOfHandles(loop) = scatter3(nan,nan,nan,loop*10,cmap(loop,:)/255);
end
legend(VectorOfHandles,{num2str(values(1)),num2str(values(2)),...
num2str(values(3)),num2str(values(4)),...
num2str(values(5)),num2str(values(6))});
hold off
Walter Roberson
Walter Roberson on 8 Aug 2016
"When comparing handle objects, use == to test whether objects have the same handle. Use isequal to determine if objects with different handles have equal property values."

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!