Matlab legend for two plots only applies to second plot - matlab

I need to plot data of two vectors, and want the data points of each to be shown in a different colour that is explaned in a legend. However, the code below displays only the legend for the second one. What am I doing wrong?
for i_plot = 1 : plot_step : N
subplot(N, 1, i_plot)
h_A = plot(bookmarksA(i_plot, :),0,'b.','MarkerSize',24);
legend('a');
xlim ([0 pieceDuration])
set(gca, 'yTick', []);
title(subj_string(i_plot,:))
hold on
h_Z = plot(bookmarksZ(i_plot, :),0,'r.','MarkerSize',24);
legend(h_Z, 'z');
end

You're only passing one label / handle combination to the legend command at a time. For a given axes, each call to legend overrides previous calls to legend, deleting previous legends rather than adding to an existing legend. You'll want to call legend once with both plot handles and labels.
legend([h_A, h_Z], {'a', 'z'})
Update
Since in your case h_A and h_Z are arrays of plot handles with identical appearances, you can just pass the first item from h_A and h_Z to legend.
legend([h_A(1), h_Z(1)], {'a', 'z'})

Related

matlab adding single legend for multiple data

figure(1);
hold on;
na=4;
circle_X = [0 0 5 5]';
circle_Y = [0 3 0 3]';
for a = 1:na
r=0.3;
N=100;
theta=linspace(0, 2*pi, N);
cx=r*cos(theta)+circle_X(a);
cy=r*sin(theta)+circle_Y(a);
plot3(cx , cy, 300*ones(N), 'r', 'linewidth', 2,'DisplayName',sprintf('circle'));
end
legend('show');
I want to draw 4 circles and add a single legend 'circle' indicating 4 circles all at once, without using "legend('circle')".
For now the legend looks like this
how should I change the code?
First, you don't need plot3, you can achieve the same figure with plot, and probably the long legend is because of that.
just change the line of plot to that:
plot(cx , cy, 'r', 'linewidth', 2,'DisplayName','circle');
Now, the legend will have 4 entries because you draw four objects. If you want a single entry you have some ways:
add the legend inside the loop, after an if statement. For example,
if a==1 ,
legend('show');
end
get handles for your plots, and legend just one of them. It can be done directly from legend, but then you will need to specify the string:
for....
h(a)=plot...
end
legend(h(1),'circle')
get handles like in part 2, and if you don't want specify the string 'circle', you can use the undocumented hasbehavior:
for...
h(a)=plot...
end
hasbehavior(h(2),'legend',false);
hasbehavior(h(3),'legend',false);
hasbehavior(h(4),'legend',false);
l=legend('show');

Choosing specific line to legend in different matlab runs

I have made a simulation that calculates trajectories of objects and plot it.
The figure looks like this:
figure(1)
plot(ArrayRT1,ArrayRT2);
hold on
plot(ArrayRD1,ArrayRD2);
plot(ArrayRM1,ArrayRM2);
title('Interception Trajectory')
xlabel('Downrange (Kft)')
ylabel('Altitude (Kft) ')
grid on
Where:
plot(ArrayRT1,ArrayRT2) - 1st object trajectory
plot(ArrayRD1,ArrayRD2) - 2nd object trajectory
plot(ArrayRM1,ArrayRM2) - 3rd object trajectory
Now, I run the same simulation without closing the figure with different initial conditions to check how they affect the trajectories so basically after the 2nd run I will have 6 lines on my graph.
How can I choose when I make legend to show legend only for 4 lines:
1,2,3 from first run and the 6th (the 3rd from the 2nd run)
Thank you.
Option 1
Use the syntax legend(subset,___) to set a legend only to specific objects in you axes. This requires getting the handles to all these objects. You can do that by assigning then to an array of handles, as in the following example:
x = 1:10;
% plotting all the lines:
figure(1)
hold on
p(1) = plot(x,2*x);
p(2) = plot(x,3*x);
p(3) = plot(x,4*x);
p(4) = plot(x,2*x+1);
p(5) = plot(x,3*x+1);
p(6) = plot(x,4*x+1);
hold off
% set the legend to a subset of the lines
legend(p([1:3 6]),{'Line 1', 'Line 2','Line 3','Line 6'})
Alternatively, you can 'tag' the lines to whom you want to attach a legend and use findobj to locate their handles, as done in option 2 below.
Option 2
You can set the property DisplayName for your plots to something like "no legend" (or any other string) and then use a loop to turn it off for these specific plots. Here is an example:
x = 1:10;
% plotting all the lines:
figure(1)
hold on
plot(x,2*x,'DisplayName','Line 1');
plot(x,3*x,'DisplayName','Line 2');
plot(x,4*x,'DisplayName','Line 3');
plot(x,2*x+1,'DisplayName','no legend'); % tag for no legend
plot(x,3*x+1,'DisplayName','no legend');% tag for no legend
plot(x,4*x+1,'DisplayName','Line 6');
hold off
% set the legend off for all lines with 'no legend'
set_leg_off = findobj('DisplayName','no legend');
for k = 1:numel(set_leg_off)
set_leg_off(k).Annotation.LegendInformation.IconDisplayStyle = 'off';
end
% show the legend
legend show
Note that:
You don't need to set the DisplayName for all the lines, only for those you want to remove from the legend. However, if you just write legend show it will ignore them when counting the data lines, so if you omit the DisplayName only for line 6, it will give it the label "data1".
You can use other property like tag to mark the non-legend lines (or any other property that will distinguish between the line you want to plot and those you don't), and then if you decide later to show them they won't appear with the label "no legend". Just remember to correct the findobj call to the property you use.
Keep in mind that changing object's tag or DisplayName does not effect the appearance of them in the legend, this is only a way to mark them for the findobj function, so you can loop only on them and turn the legend off. If you want to turn the legend on later, you need to use this loop again.
In both cases, the result is:

MATLAB: plotting subplots in for loop

I'm trying to plot several subplots in a single figure.
The total number of subplots is dependent on the maximal value in a matrix: maximal value of 'i'.
I'd like to plot two variables in two subplots below each other for every value of i :slagtijd_start & slagfrequentie_start
So when the maximum value of i = 3, we have a subplot matrix of 2x3 axes,
if i = 4 --> 2x4 axes etc.
Plotting on the right postions works, except that matlab erases the previous subplots (previous values of i). In this case i = 3 and the figure only displays the two latest subplots. I've tried different things with 'hold on' etc. But I can't figure it out. It's probably a simple trick.
I've posted my code and resulting figure below,
Thanks in advance,
Mochje
figure(6)
hold on
for i = 1:max(piektijden_start(:,2))
startnummer = find(piektijden_start(:,2) == i);
slagtijd_start= diff(piektijden_start(startnummer));
slagfrequentie_start= (60./slagtijd_start);
subplot(2,i,i),plot(piektijden_start(startnummer(1:end-1),1),slagtijd_start)
hold on
xlabel('Tijd [s]')
ylabel('Slagtijd [s]')
title('Slagtijd')
subplot(2,i,i+i),plot(piektijden_start(startnummer(1:end-1),1),slagfrequentie_start)
hold on
plot(piektijden_start(startnummer(1:end-1),1),slagfrequentie_start,'.r')
xlabel('Tijd [s]')
ylabel('Slagfrequentie [N/min]')
title('Slagfrequentie')
end
Use something like
figure(6)
hold on
max_i = max(piektijden_start(:,2));
for i = 1:max_i
%// ...
subplot(2, max_i, i)
%// ...
subplot(2, max_i, i+max_i)
%// ...
end
The second argument to subplot is the number of subplot columns. The third is the addressed subplot, such that such that the first subplot is the first column of the first row, the second subplot is the second column of the first row, and so on

MATLAB : Plot multiple lines in a single graph with different colors and Legend them.

slip_percent is plotted on y axis vs nInc(Values of 'nInc' and 'numofContacts' are obtained while running the code)
slip_percent = cell(1,numofContacts);
for nC=1:numofContacts
slip_percent{nC} = ShearCapacity(:,(5*nC));
end
Slip_percent{nC}'s are column matrices which should be plotted on same graph using different colors and legend them. If numofContacts(nC) is fixed, then the solution would be simple.
I tried the following code, but it plots all the lines in same color
'Leg' : this array contains the following elements : CaseA,CaseB,-----CaseZ,CaseAA,---,CaseZZ.
Suppose numofContacts = 3, there are 3 columns in slip_percent , then the three columns must be plotted in same graph with different colour and they must be named as CaseA,CaseB and CaseC resp.
hold on
x = linspace(0,nInc);
for g=1:numofContacts
plot(slip_percent{g})
legend(Leg(g));
xlabel('Load Increment');
ylabel('% of Bolt Slip');
hold off
end
Can anyone help me plot the lines in different colors and how to name them ?
Thank You
You can use legend with a string cell array argument to provide several legends.
Also try replacing hold on with hold all
hold all
for g=1:numOfContacts
plot( slip_percent{g});
end
legend( Leg );
xlabel('Load Increment');
ylabel('% of Bolt Slip');

Dynamic Legend (Updates in every recursion)

I got a for i=1:15. Inside I generate a variable d=1:0.01:10, which is the x'x axis and based on this, I create a continuous function F(d) which has 2 unique variables pitch and yaw. I then plot this using different colors in every recursion using cmap = hsv(15);. So then it is:
d=1:0.01:10;
cmap = hsv(15);
for i=1:15
pitch = unidrnd(10);
yaw = unidrnd(10);
for j=1:length(d)
F(j) = d(j)*3*pitch*yaw; %// some long calculation here
end
p1 = plot(d,F,'Linewidth', 1.0);
title ('blah blah')
set(p1, 'Color', cmap(i,:));
hold on;
legend (['pitch,yaw:', num2str(pitch) num2str(yaw)])
end
hold off;
This code updates the unique pitch, yaw values in every recursion (without space between them so it is kind irritating) but fails to:
Apply the proper color, visible in the figure.
Hold the color from the previous iteration and the values of pitch,yaw.
Semidocumented Solution
Adding lines to a legend in a loop can be accomplished with "dynamic legends", as described on undocumentedmatlab.com.
The idea is to replace the legend command with:
legend('-DynamicLegend');
Then update the plot command with a DisplayName parameter:
plot(d,F,'Linewidth',1.0,'DisplayName',sprintf('pitch,yaw: %d,%d',pitch,yaw));
Then plots that are added to the axes get added to the legend:
If semi-documented features are not your cup of tea, use the DisplayName trick and simply toggle the legend off/on. That is, instead of -DynamicLegend:
legend('off'); legend('show');
A different variation that does not use either DisplayName or -DynamicLegend is to delete and recreate the legend with an array of stored strings.
Official Solution
The official solution recommended by MathWorks it so grab the existing legends` line handles and manually update the legend with those handles. This is pretty painful by comparison to the dynamic legend solution above:
% Get object handles
[LEGH,OBJH,OUTH,OUTM] = legend;
% Add object with new handle and new legend string to legend
legend([OUTH;p1],OUTM{:},sprintf('pitch,yaw: %d,%d',pitch,yaw))
As an HG2 (default in R2014+) alternative to #chappjc's official MW solution, one can take advantage of legend being re-implemented as its own class rather than a kludge of other graphics objects. This has cleaned up things a bit so they are simpler to interact with.
Though these new legend objects do not have an exposed property linking legend items to plotted objects, they do have such a property, 'PlotChildren', which is an array of object handles.
For example:
x = 1:10;
y1 = x;
y2 = x + 1;
figure
plot(x, y1, 'ro', x, y2, 'bs');
lh = legend({'Circle', 'Square'}, 'Location', 'NorthWest');
pc = lh.PlotChildren
Returns:
pc =
2x1 Line array:
Line (Circle)
Line (Square)
To update our legend object without calling legend again, we can modify the 'PlotChildren' and 'String' properties of our existing legend object. As long as there is a 'String' entry for each object in 'PlotChildren', it will be rendered in the legend.
For example:
y3 = x + 2;
hold on
plot(x, y3, 'gp');
% To make sure we target the right axes, pull the legend's PlotChildren
% and get the parent axes object
parentaxes = lh.PlotChildren(1).Parent;
% Get new plot object handles from parent axes
newplothandles = flipud(parentaxes.Children); % Flip so order matches
% Generate new legend string
newlegendstr = [lh.String 'Pentagram'];
% Update legend
lh.PlotChildren = newplothandles;
lh.String = newlegendstr;
Which returns:
This functionality can be wrapped into a generic helper function to support appending one or more legend entries. We've done so with legtools on GitHub
As of MATLAB 2017a, legends update automatically when adding or removing graphics objects.
Thus, nothing specific needs to be done now. One creates the legend, then in a loop one can add lines to the axes and they'll automatically appear in the legend.