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

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.

Related

MATLAB: Blanked Plots when Looping on a Multidimensional Array

My goal output is to have four plots displaying (time, dist_a), (time, speed_a), (time, dist_b), and (time, speed_b) when looping through a multidimensional array. However, I am displaying only 2 blanked plots.
Here is my code:
time = rand(10, 1)
dist_a = rand(10,1)
dist_b = rand(10,1)
speed_a = rand(10,1)
speed_b = rand(10,1)
dist = cat(2, dist_a, dist_b);
speed = cat(2, speed_a, speed_b);
for k = 1:2
figure;
plot(time, dist(k));
plot(time, speed(k));
end
Your problems were two-fold. Firstly, you were only plotting a single point as opposed to a vector, changing dist(k) to dist(:,k) for example fixes this. Secondly, if you want four figures with a loop that executes twice, you need to include another figure command before the second plot. The following should do what you asked for, I also added in some formatting to make the plots looks nicer
for k = 1:2
figure
plot(time, dist(:,k),'o','LineWidth',2);
xlabel('time')
ylabel('distance')
box on
grid on
figure
plot(time, speed(:,k),'o','LineWidth',2);
xlabel('time')
ylabel('speed')
box on
grid on
end
which gives:

Plot to figures without bringing them into foreground

figure;
ax1 = axes;
figure;
ax2 = axes;
x = 0; y = 0;
while ishandle(ax1) && ishandle(ax2)
x = x + 1;
y = y + 1;
figure(1)
scatter(x,y, 'MarkerEdgeColor', 'red')
hold on
figure(2)
scatter(x,y, 'MarkerEdgeColor', 'blue')
hold on
end
In my script I have multiple figures, which are going to be updated in a loop. The figures have to be displayed, while the script is running. Unfortunately the currently updated figure is always popping in the foreground, which makes it impossible to monitor a certain figure. I understand that the calling of figure(1) and figure(2) causes this behaviour, but I how can I plot to these figures, without bringing the window into foreground?
As mikkola suggested in a comment, you can specify to which axes scatter or plot add data points. However, there is a better method: create a single line object, and update its xdata and ydata properties. This is both faster and more memory efficient. Your code would become:
x = 0; y = 0;
figure;
h1 = plot(x,y,'ro');
figure;
h2 = plot(x,y,'bo');
while ishandle(h1) && ishandle(h2)
x = x + 1;
y = y + 1;
h1.XData(end+1) = x;
h1.YData(end+1) = y;
h2.XData(end+1) = x;
h2.YData(end+1) = y;
drawnow
pause(0.1)
end
I keep a set of rules of thumb for when working with MATLAB handle graphics. These are relevant to this question:
Use figure only to create a new figure, or to bring an existing figure to the front (which you want to avoid in general, but sometimes is necessary).
Always specify with which figure or axes you want to work, by keeping and using their handles. I never rely on gcf or gca (not explicitly nor implicitly). Using the current figure is useful when typing on the command line, but in a script or a function there is the real danger than someone clicks randomly on windows while the function is executing. Creating a window then writing to gcf could end up writing to a different figure (really, I click on random things all the time).
Don't create more objects than necessary. Creating a new line object for every point you plot is wasteful.
Note also that plot(...'o') is equivalent to scatter(...) unless you specify a different color or size for each point. But using the dot size or color to specify additional information is not a good way to convey that information. Read Tufte's "The visual display of quantitative information" if you're interested in learning about effective communication through graphs.
The relevant part can be found in the part of the documentation of scatter that includes the input ax:
scatter(ax,___) plots into the axes specified by ax instead of into
the current axes.
This allows the user to specify an axis handle pointing to which axes should be used for drawing the scatter plot. Thus if you skip using figure in your code and use the ax input instead, you avoid the "bring to front" behavior associated with figure.
You can modify your code as follows:
figure;
ax1 = axes;
figure;
ax2 = axes;
x = 0; y = 0;
while ishandle(ax1) && ishandle(ax2)
x = x + 1;
y = y + 1;
scatter(ax1, x,y, 'MarkerEdgeColor', 'red')
hold on
scatter(ax2, x,y, 'MarkerEdgeColor', 'blue')
hold on
end

Matlab update plot with multiple data lines/curves

I want to update a plot with multiple data lines/curves as fast as possible. I have seen some method for updating the plot like using:
h = plot(x,y);
set(h,'YDataSource','y')
set(h,'XDataSource','x')
refreshdata(h,'caller');
or
set(h,'XData',x,'YData',y);
For a single curve it works great, however I want to update not only one but multiple data curves. How can I do this?
If you create multiple plot objects with a single plot command, the handle returned by plot is actually an array of plot objects (one for each plot).
plots = plot(rand(2));
size(plots)
1 2
Because of this, you cannot simply assign another [2x2] matrix to the XData.
set(plots, 'XData', rand(2))
You could pass a cell array of new XData to the plots via the following syntax. This is only really convenient if you already have your new values in a cell array.
set(plots, {'XData'}, {rand(1,2); rand(1,2)})
The other options is to update each plot object individually with the new values. As far as doing this quickly, there really isn't much of a performance hit by not setting them all at once, because they will not actually be rendered until MATLAB is idle or you explicitly call drawnow.
X = rand(2);
Y = rand(2);
for k = 1:numel(plots)
set(plots(k), 'XData', X(k,:), 'YData', Y(k,:))
end
% Force the rendering *after* you update all data
drawnow
If you really want to use the XDataSource and YDataSource method that you have shown, you can actually do this, but you would need to specify a unique data source for each plot object.
% Do this when you create the plots
for k = 1:numel(plots)
set(plots(k), 'XDataSource', sprintf('X(%d,:)', k), ...
'YDataSource', sprintf('Y(%d,:)', k))
end
% Now update the plot data
X = rand(2);
Y = rand(2);
refreshdata(plots)
You can use drawnow:
%Creation of the vectors
x = 1:100;
y = rand(1,100);
%1st plot
h = plot(x,y);
pause(2);
%update y
y = rand(1,100);
set(h,'YData',y)
%update the plot.
drawnow

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');

matlab plotting a family of functions

Generate a plot showing the graphs of
y=(2*a+1)*exp(-x)-(a+1)*exp(2*x)
in the range x ∈ <-2, 4> for all integer values of a between -3 and 3
I know how to make typical plot for 2 values and set a range on the axes, but how to draw the graph dependent on the parameter a?
To elaborate on Ben Voigt's comment: A more advanced technique would be to replace the for-loop with a call to bsxfun to generate a matrix of evaluations of M(i,j) = f(x(i),a(j)) and call plot with this matrix. Matlab will then use the columns of the matrix and plot each column with individual colors.
%%// Create a function handle of your function
f = #(x,a) (2*a+1)*exp(-x)-(a+1)*exp(2*x);
%%// Plot the data
x = linspace(-2, 4);
as = -3:3;
plot(x, bsxfun(f,x(:),as));
%%// Add a legend
legendTexts = arrayfun(#(a) sprintf('a == %d', a), as, 'uni', 0);
legend(legendTexts, 'Location', 'best');
You could also create the evaluation matrix using ndgrid, which explicitly returns all combinations of the values of x and as. Here you have to pay closer attention on properly vectorizing the code. (We were lucky that the bsxfun approach worked without having to change the original f.)
f = #(x,a) (2*a+1).*exp(-x)-(a+1).*exp(2*x); %// Note the added dots.
[X,As] = ndgrid(x,as);
plot(x, f(X,As))
However for starters, you should get familiar with loops.
You can do it using a simple for loop as follows. You basically loop through each value of a and plot the corresponding y function.
clear
clc
close all
x = -2:4;
%// Define a
a = -3:3;
%// Counter for legend
p = 1;
LegendText = cell(1,numel(a));
figure;
hold on %// Important to keep all the lines on the same plot.
for k = a
CurrColor = rand(1,3);
y= (2*k+1).*exp(-x)-(k+1).*exp(2.*x);
plot(x,y,'Color',CurrColor);
%// Text for legend
LegendText{p} = sprintf('a equals %d',k);
p = p+1;
end
legend(LegendText,'Location','best')
Which gives something like this:
You can customize the graph as you like. Hope that helps get you started!