Loren on the Art of MATLAB

Hold Everything! 31

Posted by Loren Shure,

Have you ever tried to overlap more than one plot, only to find that you had to fiddle with a few times before it looked right? Perhaps this is because you aren't take full advantage of the function hold.

Contents

An Example

Suppose I want to plot two sets of data or functions on the same plot. How might I do that? There are several ways. Let's create some data and a function.

t = 0:0.005:1;
f = @(t) sin(2*pi*10*t);
s = f(t);
sn = s + 0.3*randn(size(t));

Plot the Data and the Function

If I have everything assembled up front, I can plot all the values at once. The function plot is smart enough to cycle through colors for multiple lines.

plot(t,s,t,sn)
legend('signal','signal with noise','Location','SouthEast')

Try Another Way

Suppose we have the first data values.

plot(t,s)

And then need to add some more values later. Here's a way I can do this.

hold on
plot(t,sn)
legend('signal','signal with noise','Location','SouthEast')
hold off

But the plot is a bit confusing, no? The legend isn't very helpful since each plot has the same color and linestyle. Instead, I can specify the color(s) I want with the plot commands.

plot(t,s)
hold on
plot(t,sn,'g')
legend('signal','signal with noise','Location','SouthEast')
hold off

That green is too bright. To use the one from the first plot, I can find out the correct green color by looking at the defaults.

allcolors = get(0,'defaultAxesColorOrder')
allcolors =
            0            0            1
            0          0.5            0
            1            0            0
            0         0.75         0.75
         0.75            0         0.75
         0.75         0.75            0
         0.25         0.25         0.25

You can see that the green is definitely toned down (the color represented by RGB values in the allcolors(2,:).

plot(t,s)
hold on
plot(t,sn,'color',allcolors(2,:))
legend('signal','signal with noise','Location','SouthEast')
hold off

Why Use Hold?

Why use hold at all if it's giving me headaches? Because sometimes I want to add data to the plot using a different plot function. Here's an example.

fplot(f, [0 1])
hold on
plot(t,sn,'color',allcolors(2,:))
legend('signal','signal with noise','Location','SouthEast')
hold off

A Better Way

Surely there must be a better way than managing the colors on your own. And there is! The all option to hold magically (quoting from the doc)

holds the plot and the current line color and line style so that subsequent plotting commands do not reset the ColorOrder and ColorOrder property values to the beginning of the list. Plotting commands continue cycling through the predefined colors and linestyles from where the last plot stopped in the list.

Let's try it.

fplot(f, [0 1])
hold all
plot(t,sn)
legend('signal','signal with noise','Location','SouthEast')
hold off

NOTE: I updated this since I didn't use hold off in my examples earlier so old lines were overwriting new ones in the legend. Much better now.

Will hold all Help You?

I'd be curious to hear if the behavior of hold all helps you out. Let me know here.


Get the MATLAB code

Published with MATLAB® 7.8

31 CommentsOldest to Newest

nice little blog, loren…

in general, i use LINE (which should be mentioned as well)…
-and- i never use PLOT in situations where more than one line needs to be drawn…

HOLD is a cumbersome…
in particular, because there is no simple syntax, which returns the current stage; and one easily forgets to reset it afterwards (at least up to ver 2008b)…

us

Urs-

You can use ishold to inquire about the state of hold. I chose to talk about high level commmands because they can be useful to users without rolling their own, e.g., bar, fplot, …

–Loren

Hey hey, “hold all”… now there’s a useful piece of info I wasn’t aware of.

Note, the legends in the blog post don’t seem to have updated colours according to the linestyles in your code.

Cheers,
Sven.

Sven-

Hej, hej! I am embarassed to say that I didn’t notice that about the legends. I will create a bug report. Thank you.

–Loren

yes, i should have mentioned ISHOLD…
but as i said: SIMPLE syntax…
something like

ocd=cd;
cd(to-a-folder);
cd(ocd);

because HOLD – unfortunately – does not take a logical (as of 2008b)…

again, thanks for the blog
urs

The legend colors will be correct if you supply the legend command with the handles to the lines, as below:

h1 = plot(t,s);
hold all
h2 = plot(t,sn);
legend([h1;h2],'signal','signal with noise','Location','SouthEast')

-Rob

Thanks, Rob. But I don’t think there’s a real impediment to getting the lines right without supplying the handles. I could well be wrong though!

–Loren

I have used the hold all command successfully in the past.

I would love to see a discussion on use of patches, though. I have used transparent patches to “overlay” regions on other plots, using hold and hold all. However, my use of patches was really more art than science. Understanding how to use the handles generated by the patch command would be really great!

Sven et al – there is a semi-documented feature of the legend function that does exactly what you want:

legend(hAxes,'-DynamicLegend',...)

This causes the legend to be automatically updated when plot lines are added/removed/changed in the axes.

Note: “semi-documented” means that it’s not listed in the main help or doc sections, but if you open legend.m in an editor you’ll see it being described immediately following the main help section at the top. I’m not exactly sure what this means in terms of supportability in future Matlab releases, but this particular feature has existed many releases back (Matlab 7.1 for sure, perhaps earlier).

Dear Loren, this post just brightened up my day! I use hold very often and was bugged by having to manually manage colors (and then if I want to cycle linestyles when printing in B&W it gets ugly). “hold all” saves the day! Thanks!

Hi
I’ve run the last example on R2008a and the legend on the figure is ok (blue and green).
Maybe it is in the html/screenshot generation that it went wrong?

Thanks for the plot Loren. I think there are quite a fiew FEX contributions to plot with automatic color cycling (see ex. plota). They were useful before hold got the option ALL!

-Thierry

Hej Loreen,

first of all thanks for the blog, I appreciate your ideas and tips.

When I read this one I thought I could ask a question that is related but is not quite congruent.

The situation I fac quite frequently is that I plot two sets of data to compare like this:

plot(time1,data1)
hold on
plot(time2,data2,'r')

I am not all that itchy about the exact colors and things. However, what frequently happens is that data1 and data2 are scaled differently so data2 reners data1 as a flat line in the plot, another thing is that time1 and time2 might be different units (time1 in sceonds time2 in ms).

The only solutions I know of so far are a) be really careful before you plot (well …) b) start over again with clf.

What I am looking for would be some “undo” command that removes the effect of the last plot command so I could do

plot(time1,data1)
hold on
plot(time2,data2,'r')

UNDO THE LAST PLOT

data2 = scale_function(data2);
plot(time2,data2,'r')

This would be especially convenient in situations where data1 gets erased from memory or is in different levels of memory.

Cheers
Harald

Harald-

If you get the handles to the plots, e.g.,

hold on
h1 = plot(....)
h2 = plot(...,'r')

then you can just use delete to get rid of the lines you don’t want, e.g.,

delete(h2)

With different scale data, you might want to try plotyy as well.

–Loren

The colors of the lines in the legend of the last example are correct in 2008b and 2009a. Something else must have happened in the example here.
The line styles and colors seem to get updated automatically in the legend if changed.
FaceAplha of patch objects is not updated in legend though

Anyway, nice to know I had not noticed this hold all.
I don’t use hold much, or plot. I usually end up tweaking each line saparately anyway, so I use line in the first place.

Folks-

My bad. I forgot to insert hold off between my plots so old lines were being held onto and plotted on top of new ones. legend seems fine. I updated the post to insert the commands and recreate the graphs.

–Loren

I’ve recently been plotting several quantities on the same axes that have required the use of hold. I appreciate the tip and will try it in the future.

One approach that I’ve been trying recently is building my arguments in a cell array as I’m assembling what I what plotted rather than call subsequent plot/line, etc. I doesn’t make any sense really for a single plot, but I found myself reusing the plot variables many times, like when I have a series of baselines to compare against, and putting them in a cell array made for a nice compact way to plot the same quantities again.

curvs_baseline=[{x1} {y1} {'r-'}];
...
cv=[curvs_baseline {xn} {yn} {'g-'}];
hc=plot(cv{:})

All in all, I’ve been finding lots of new uses for cell arrays, that I’m still discovering after 10+ years programming in MATLAB.

I just had a hold-related problem and remembered this blog post. As Urs commented saving the hold state isn’t simple. ishold doesn’t seem to distinguish between “hold on” and “hold all” so I had to grab gcf properties with get.

Saving the hold state and reinstating is polite in utility plotting functions. I second the thought that being able to do something like the following would be nice built in behavior:

% Save state
old_hold = hold;
...
% do stuff including hold on/off/all commands
...
% Reinstate state
hold(old_hold);

The “hold all” command is one of the most useful when plotting data. In fact, in my first year using MATLAB I only knew about “hold on” and “hold off” (as apparently many here), and was a bit annoyed at times. How relieved was I when some day I learned this “hold all” trick.

Together with the pratice to save handles from plots and include them in the legend-command, “hold all” is one of the very first things I teach MATLAB newbies (if I get the chance).

Hi! i just found your blog. Thanks for making the effort. I currently use “hold all” in my multiline plot and it works fine. I did not know I can use “line” as well.

Dear all,

I have different 1d vectors to be plotted as curves into a single Figure. The y values across the vectors is not normalized. Therefore, I’ve some vectors with pretty small y-values (10^-8), and others ranging from [0-1]. The highest value of a given vector is always 1.
Because of this, when I plot all the vectors together, some curves are almost displayed as being the x-axis (since the y-values are small). Is there any function that allows to normalize everything together, so as to be able to visualize the curves properly?

Best wishes

Javier-

There is no function. You’d have to decide how to scale each of your curves yourself. Another alternative may be to plot them in a log y-axis. You can try this with semilogy, assuming all the values are non-negative.

–loren

i have problem in legend. i have plot six signal and now i want to assign legend to the first and last means sixth signal how can do that.

I just spend a day figuring out that the array I was trying to plot was too long. I followed your example and it worked perfectly, then I followed your example with my matrix and it did not work, but I discovered a work around for long sets of data. Instead of…

plot(X1,Y1,'color',[0 0 1])
hold on
plot(X2,Y2,'color',[0 0.5 0])
hold off
legend('a','b')

I had to do…

plot(X1(1:length(X1)),Y1(1:length(X1)),'color',[0 0 1])
hold on
plot(X2(1:length(X2)),Y2(1:length(X2)),'color',[0 0.5 0])
hold off

I am not sure how long your data has to be before you have to use this method, but mine had 1729 data points.

I should have added

legend('a','b')

to the end of my previous comment as my problem was that the legend was displaying the same color for both plots even though they plotted in different colors.

Dave-

This makes not sense to me. I think you should contact technical support (link on right of blog page) with sample data and script plus error. Also information about your computer. I can easily plot 1749 points without even thinking about it. Indexing in shouldn’t make it more possible.

–Loren

Dave-

Still makes no sense to me. Indexing shouldn’t help here. Did you try omitting the color and use “hold all” instead of “hold on”? Then add the legend.

–Loren

Hi,
I use hold all inside a for loop to represent several data in a GUI axes:

for i=1:length(filedata)
    % more data processing code here
    plot(handles.axes,processed_datax,processed_datay),  
    hold all
end

It works fine, as always I have used it. However, the data processing takes some time to compute so I decided to add a waitbar:

h = waitbar(0, 'computing...')
for i=1:length(filedata)
    waitbar(i/length(filedata),h)
    % more data processing code here
    plot(handles.axes,processed_datax,processed_datay),  
    hold all
end
close (h)

In this case, the hold stops working. Apparently, the fact that waitbar interrupts the for clears the hold in some way…
How do you work around this?

Ok, I have found the answer. I have to indicate hold which figure has to hold:

 hold(handles.axes,'all')

These postings are the author's and don't necessarily represent the opinions of MathWorks.