MATLAB graph plotting: assigning legend labels during plot - matlab

I am plotting data in a typical MATLAB scatterplot format. Ordinarily when plotting multiple datasets, I would use the command 'hold on;', and then plot each of the data, followed by this to get my legend:
legend('DataSet1', 'DataSet2') % etcetera
However, the (multiple) datasets I am plotting on the same axes are not necessarily the same datasets each time. I am plotting up to six different sets of data on the same axes, and there could be any combination of these shown (depending on what the user chooses to display). Obviously that would be a lot of elseif's if I wanted to setup the legend the traditional way.
What I really would like to do is assign each DataSet a name as it is plotted so that afterwards I can just call up a legend of all the data being shown.
...Or, any other solution to this problem that anyone can think of..?

You should be able to set the DisplayName property for each plot:
figure
hold on
plot(...,'DisplayName','DataSet1')
plot(...,'DisplayName','DataSet2')
legend(gca,'show')
http://www.mathworks.com/help/matlab/ref/line_props.html
Side Note: I've found a lot of little tricks like this by getting the figure to look the way I want, then choosing the Figure's "File" menu option "Generate M-File..." and inspecting the generated output code.

One option is to take advantage of the 'UserData' property like so:
figure;
hold on
plot([0 1], [1 0], '-b', 'userdata', 'blue line')
plot([1 0], [1 0], '--r', 'userdata', 'red dashes')
% legend(get(get(gca, 'children'), 'userdata')) % wrong
legend(get(gca, 'children'), get(get(gca, 'children'), 'userdata')) % correct
Edit: As the questioner pointed out, the original version could get out of order. To fix this, specify which handle goes with which label (in the fixed version, it is in the correct order).

Use 'DisplayName' as a plot() property, and call your legend as
legend('-DynamicLegend');
My code looks like this:
x = 0:h:xmax; %// get an array of x-values
y = someFunction; %// function
plot(x, y, 'DisplayName', 'Function plot 1'); %// plot with 'DisplayName' property
legend('-DynamicLegend',2); %// '-DynamicLegend' legend
Source: http://undocumentedmatlab.com/blog/legend-semi-documented-feature/

You can try something like the following
for k = 1:10
h(k) = plot(...);
name{k} = ['condition ' num2str(k)];
end
legend(h, name);

Make a for loop. But Before the for loop, make an array.
%for example
legendset = {}
for i = 1:10
%blabla
%Then in the fore loop say:
legendset = [legendset;namedata(i)]
%It puts all names in a column of legendset.
%Make sure namedata are characters.
%foreloop ends
end
%Then after the foreloop say:
legend(legendset).

Related

Plotting functions in one figure with parameters given by a vector (color issue)

I want to plot four straight lines with different slopes given by a vector $A$:
A=[1.1,2.3,7.9];
k=0;
x=-1:0.01:1;
for n=1:3
plot(x,A(n)*x)
hold on
end
However, it turns out that all lines are of the same color (blue). How do I plot them in different colors, but still using for-end command? (this is necessary when the vector $A$ is huge...)
Actually it can be solved by putting a "hold all" before for-end loop:
A=[1.1,2.3,7.9];
k=0;
x=-1:0.01:1;
hold all
for n=1:3
plot(x,A(n)*x)
end
I am using 2013a. Not sure other versions of Matlab have the same issue and solution.
You could make a colormap (e.g. lines) to specify the colors for all the different lines. By using set on the handle to the lines, you don't have to use a for loop.
A=[1.1,2.3,7.9];
x=-1:0.01:1;
cmap = lines(numel(A));
p = plot(x,A.'*x);
set(p, {'color'}, num2cell(cmap,2));
Alternatively, if you do want to use a for loop, you can set the color using the same colormap, on each loop iteration:
figure()
axes;
hold on;
cmap = lines(numel(A));
for n = 1:numel(A)
plot(x,A(n)*x, 'Color', cmap(n,:));
end
Use the following
A=[1.1 2.3 7.9];
x=[-1 1]; % use this instead of x=-1:0.01:1
line(x,A'*x);
result:
Also, if you wish to manipulate the colors manually, use the following code:
A=[1.1 2.3 7.9];
L=length(A);
col_mat=rand(L,3); % define an arbitrary color matrix in RGB format
x=[-1 1]; % use this instead of x=-1:0.01:1
p=line(x,A'*x);
%% apply the colors
for i=1:L
p(i).Color=col_mat(i,:);
end

Prevent specific plot entry from being displayed on a MATLAB plot legend

I need to prevent a specific plot entry from being displayed on a Matlab plot legend.
Sample:
% x and y are any plot data
for i=1:5
plot(x,y);
plot(x2,y2,'PleaseNoLegend!'); % I need to hide this from legend
end
legend('show');
Is there any flag I can set inside the plot command so this specific entry doesn't show up in legend?
You can achieve that by setting the 'HandleVisibility' property to 'off'. Note that this hides the handles of those plots to all functions, not just to legend.
For example,
hold on
for k = 1:3
x = 1:10;
y = rand(1,10);
x2 = x;
y2 = y + 2;
plot(x,y);
plot(x2,y2,'--','HandleVisibility','off'); % Hide from legend
end
legend('show')
produces the graph
You can use the semi-documented function called hasbehavior, that allows you to ignore individual plots in a legend after you issued the plot command.
figure;
hold on;
for i=1:5
plot(x,y);
h = plot(x2,y2);
hasbehavior(h,'legend',false);
end
legend('show');
The fact that it's semi-documented suggests that it could break sooner or later in a newer MATLAB version, so use with care. It might still be a convenient choice for certain applications.
As #stephematician noted, this MATLAB built-in is also unavailable in Octave, which might be another reason why the other answers are preferable.
As Luis Mendo mentions (and I somehow missed this) the handle is hidden to all other functions in his answer, which will be ok in most situations, but an alternative solution which looks identical to the above and doesn't have this effect is:
k_values = 1:3;
h = nan(size(k_values));
x = 1:10;
hold on
for k = k_values
y = rand(size(x));
y2 = y + 2;
h(k) = plot(x,y);
plot(x,y2,'--');
end
hold off
legend(h, strcat('data', num2str(k_values')))
The final command sets the legend entry for each handle returned by the plot(x,y) command. The first argument is a 1x3 array of line handles which will appear in the legend, and the second argument is a 3x5 char matrix where each row is a label.

Reset ColorOrder index for plotting in Matlab / Octave

I have matrices x1, x2, ... containing variable number of row vectors.
I do successive plots
figure
hold all % or hold on
plot(x1')
plot(x2')
plot(x3')
Matlab or octave normally iterates through ColorOrder and plot each line in different color. But I want each plot command to start again with the first color in colororder, so in default case the first vector from matrix should be blue, second in green, third in red etc.
Unfortunately I cannot find any property related to the color index niether another method to reset it.
Starting from R2014b there's a simple way to restart your color order.
Insert this line every time you need to reset the color order.
set(gca,'ColorOrderIndex',1)
or
ax = gca;
ax.ColorOrderIndex = 1;
see:
http://au.mathworks.com/help/matlab/graphics_transition/why-are-plot-lines-different-colors.html
You can shift the original ColorOrder in current axes so that the new plot starts from the same color:
h=plot(x1');
set(gca, 'ColorOrder', circshift(get(gca, 'ColorOrder'), numel(h)))
plot(x2');
You can wrap it in a function:
function h=plotc(X, varargin)
h=plot(X, varargin{:});
set(gca, 'ColorOrder', circshift(get(gca, 'ColorOrder'), numel(h)));
if nargout==0,
clear h
end
end
and call
hold all
plotc(x1')
plotc(x2')
plotc(x3')
Define a function that intercepts the call to plot and sets 'ColorOrderIndex' to 1 before doing the actual plot.
function plot(varargin)
if strcmp(class(varargin{1}), 'matlab.graphics.axis.Axes')
h = varargin{1}; %// axes are specified
else
h = gca; %// axes are not specified: use current axes
end
set(h, 'ColorOrderIndex', 1) %// reset color index
builtin('plot', (varargin{:})) %// call builtin plot function
I have tested this in Matlab R2014b.
I found a link where a guy eventually solves this. He uses this code:
t = linspace(0,1,lineCount)';
s = 1/2 + zeros(lineCount,1);
v = 0.8*ones(lineCount,1);
lineColors = colormap(squeeze(hsv2rgb(t,s,v)))
ax=gca
ax.ColorOrder = lineColors;
Which should work for you assuming each of your matrices has the same number of lines. If they don't, then I have a feeling you're going to have to loop and plot each line separately using lineColors above to specify an RBG triple for the 'Color' linespec property of plot. So you could maybe use a function like this:
function h = plot_colors(X, lineCount, varargin)
%// For more control - move these four lines outside of the function and make replace lineCount as a parameter with lineColors
t = linspace(0,1,lineCount)'; %//'
s = 1/2 + zeros(lineCount,1);
v = 0.8*ones(lineCount,1);
lineColors = colormap(squeeze(hsv2rgb(t,s,v)));
for row = 1:size(X,1)
h = plot(X(row, :), 'Color', lineColors(row,:), varargin{:}); %// Assuming I've remembered how to use it correctly, varargin should mean you can still pass in all the normal plot parameters like line width and '-' etc
hold on;
end
end
where lineCount is the largest number of lines amongst your x matrices
If you want a slightly hacky, minimal lines-of-code approach perhaps you could plot an appropriate number of (0,0) dots at the end of each matrix plot to nudge your colourorder back to the beginning - it's like Mohsen Nosratinia's solution but less elegant...
Assuming there are seven colours to cycle through like in matlab you could do something like this
% number of colours in ColorOrder
nco = 7;
% plot matrix 1
plot(x1');
% work out how many empty plots are needed and plot them
nep = nco - mod(size(x1,1), nco); plot(zeros(nep,nep));
% plot matrix 2
plot(x2');
...
% cover up the coloured dots with a black one at the end
plot(0,0,'k');

Legend containing only specific plots

I have 10 curves in a plot, but only three of them should appear in the legend. For example, among 10 curves, just the first, 5th and 10th should be in the legend, how I can do this?
Here's my program:
x=1:0.5:15;
y1=x.^1
plot(x,y1)
hold on
y2=x.^1.2
plot(x,y2)
hold on
.
.
.
y10=x.^2.2
plot(x,y10)
You can use handles for the plots, and then specify the plots for the legend by their handles:
x=1:0.5:15;
y(1,:)=x.^1;
y(2,:)=x.^1.2;
...
...
...
y(10,:)=x.^2.2;
for k=1:10
h(k)=plot(x,y(k,:));
hold on
end
legend([h(1) h(5) h(10)],'curve 1','curve 5','curve 10');
hold off
legend can take a handle or handles, and a list of strings. I've taken the liberty of rewriting your code so it plots in a loop rather than creating a bunch of y variables. Generally speaking, if you find yourself creating a series of variables named y1, y2, etc, there's a better way of doing it in MATLAB.
There are 7 plots, not 10, but you get the idea.
x=1:0.5:15;
m=1:0.2:2.2;
figure
hold on
for n = 1:7
h(n) = plot(x,x.^m(n));
end
legend(h([1,3,5]),'Plot One', 'Plot Three', 'Plot Five',...
'Location', 'NorthWest')
you need to use the plot handles in the legend function to indicate the desired curves. Inserted in your code it would look like this:
x=1:0.5:15;
y1=x.^1;
h1=plot(x,y1,'r');
hold on
y2=x.^1.2;
h2=plot(x,y2,'c');
hold on
.
.
.
y10=x.^2.2;
h10=plot(x,y10,'p');
hold off;
legend([h2,h10] , 'Fart 2', 'More Fart'); % Plot in the handle you wish
Here's a slick two-liner that I use:
a=flipud(findall(gcf,'Type','Line')); %get all line objects of current plot
legend(a([1 3]),{'a','b'}) %add legend for line 1 and 3, 'a' and 'b'
The legend command only applies to the most recent created plot, unless a handle is passed.
figure
for c=1:10
subplot(4,4,c)
ezplot('y=sin(x)');
if c==5||c==10
legend('sin(x)')
end
end

In MATLAB, how does one clear the last thing plotted to a figure?

In MATLAB, I plot many different vectors to a figure. Now, what I would like to do is simply undo the last vector that I plotted to that figure, without clearing everything else. How can this be accomplished? Can it be accomplished?
Thanks
Edit:
figure(1); clf(1);
N = 100;
x = randn(1,N);
y = randn(1,N);
z = sin(1:N);
plot(x); hold on;
plot(y,'r');
plot(z,'k');
Now here, I would like to remove the plot z, which was the last plot I made.
If you know before plotting that you want to remove it again later, you can save the handle returned by plot and delete it afterwards.
figure;
h1 = plot([0 1 2], [3 4 5]);
delete(h1);
Try
items = get(gca, 'Children');
delete(items(end));
(or maybe delete(items(1)))
The answer that #groovingandi gives is the best way to generally do it. You can also use FINDALL to find the handle based on the properties of the object:
h = findall(gca, 'type', 'line', 'color', 'k');
delete(h);
This searches the current axes for all line objects (plot produces line objects) that are colored black.
To do this on, say, figure 9, you need to find the axes for figure 9. Figure handles are simply the figure number, so:
ax = findall(9, 'axes');
h = findall(ax, 'type', 'line', 'color', 'k');
delete(h);