In matplotlib.pyplot, what is the difference between plt.clf() and plt.close()? Will they function the same way?
I am running a loop where at the end of each iteration I am producing a figure and saving the plot. On first couple tries the plot was retaining the old figures in every subsequent plot. I'm looking for, individual plots for each iteration without the old figures, does it matter which one I use? The calculation I'm running takes a very long time and it would be very time consuming to test it out.
plt.close() will close the figure window entirely, where plt.clf() will just clear the figure - you can still paint another plot onto it.
It sounds like, for your needs, you should be preferring plt.clf(), or better yet keep a handle on the line objects themselves (they are returned in lists by plot calls) and use .set_data on those in subsequent iterations.
I think it is worth mentioning that plt.close() releases the memory, thus is preferred when generating and saving many figures in one run.
Using plt.clf() in such case will produce a warning after 20 plots (even if they are not going to be shown by plt.show()):
More than 20 figures have been opened. Figures created through the
pyplot interface (matplotlib.pyplot.figure) are retained until
explicitly closed and may consume too much memory.
plt.clf() clears the entire current figure with all its axes, but leaves the window opened, such that it may be reused for other plots.
plt.close() closes a window, which will be the current window, if not specified otherwise.
There is a slight difference between the two functions.
plt.close() - It altogether plots the graph in seperate windows,releasing
memory,retaining each window for view.
plt.clf() - We can say,it displays the graph in the same window one after other
For illustration, I have plotted two graphs with paramters year and views on X axis and Y axis each. Initially I have used closed function.it displayed the graphs in two seperate windows…
Afterwords, when I run the program with clf() it clears the graph and displays next one in same window i.e figure 1.
Here is the code snippet -
import matplotlib.pyplot as plt
year = [2001,2002,2003,2004]
Views= [12000,14000,16000,18000]
Views2 = [15000,1800,24000,84000]
plt.plot(year,Views)
plt.show()
plt.clf()
plt.plot(year,Views2)
plt.show()
plt.clf()
Related
I have a script which I'm adapting to include a GUI. In it, I create a plot with subplots (the arrangement of which depends on the number of plots - e.g. 4 plots go into a square rather than 4-across). That plot (with a subplot for each of the "targets" analyzed) gets saved to a .png.
In building the GUI, I'm writing up the 'results' frame and would like to show these individual subplots on their own tabs. I've written the code to lay out the frame how I want it, but in order to separate the subplots into their own plots, I need to draw the completed Axes object (e.g. the entire subplot for that target) onto a new figure in the frame.
Since the number of subplots isn't known before runtime, I already have my Axes objects/subplots in an array (/list?) axs, whose members are the individual Axes objects (each containing data points created with ax.scatter() and several lines and annotations created with ax.plot() and ax.annotate).
When I initially create the axes, I do so with
fig, axs = plt.subplots(num='Title', nrows=numrow, ncols=numcol,
figsize=[numcol*5, numrow*5],
subplot_kw={'adjustable':'box', 'aspect':1})
Is there a way to now take these axes and draw them onto a new figure (the one that will be contained in the 'results' frame of the GUI)? In my searches, I only came up with ways to plot multiple axes onto a single figure (i.e. how to use subplots()) but nothing came up on how I'd throw a pre-existing Axes object into a new figure that it wasn't originally associated with. I'd rather not re-draw the axes from scratch -- there's quite a bit of decoration and multiple datasets / lines plotted onto them already.
Any ideas? Happy to post code as requested, but since this more of a "How do I do this" than a "why doesn't my code work", I didn't post much of it.
Thank you!
I believe that's not possible and you will have to recreate the Axes objects inside the other figure. Which is just a matter of code reorganization. Note that your approach would not noticeably improve rendering performance. Matplotlib would have to re-render the Axes objects anyway, and that's the computationally expensive part. Creating the objects is relatively cheap.
What you're trying to do is pretty much this:
from matplotlib import pyplot
pyplot.ion()
figure1 = pyplot.figure()
axes = figure1.add_subplot()
axes.plot([0, 1], [0, 1])
figure2 = pyplot.figure()
figure2.add_axes(axes)
Which raises:
ValueError: The Axes must have been created in the present figure
And the documentation of add_axes() notes:
In rare circumstances, add_axes may be called with a single argument, an Axes instance already created in the present figure but not in the figure's list of Axes.
So that's a pretty clear indication that this is not a supported use case.
So I have been using matplot for a while now, and one thing that confuses me how it handles subplots.
It can be done as such:
fig = plt.figure()
ax = fig.add_subplot(1,2,1)
Or. It could be done as such:
plt.subplots(1,2)
Or, one could do this instead:
plt.subplot(211)
Or of course, if we only need one plot we can immediately run
plt.plot(x,y) # or .scatter or whatever.
Why? Is there any actual reason why you should use one over the others?
Matplotlib is a Python library, that was significantly influenced by MatLab and aimed in part at former and current MatLab users, therefore has 2 types of syntax:
MatLab syntax, plt.sublot(211); plt.plot(); plt.colorbar();, that implies that every time you create a figure or subplot it is stored inside as last active object and all plotting and changing of parameters is applied to it. It is to make it comfortable to use for those, who transitioned from MatLab. The idea is you create an element and instantly apply all actions to it, then create next and never return to previous until you call plt.show .
Classic programming syntax with explicit object declaration and operations on said objects. It is comfortable for everyone else and allows one to go back to previously created objects (figures and axes) and make additional changes.
The matlab way makes it hard to work with multiple figures. (figure is an independent picture, axes is region of that picture that you plot data in) plt.show always shows the last figure you created, example:
plt.figure() #new figure created and stored as current active
Plt.subplot() #new axes created in current figure and stored as current axes
Plt.plot() #data plotted in current axes
Plt.subplot() #second axes added to figure and made current active
Plt.plot() #plot in current active that is second now
Plt.figure() #the new figure created, old can still be found with difficulty i believe,
#but current active is now different and plt.show will not show anything you plotted before.
But some people find it better for quick and dirty plotting.
You can transition between the 2 by using fig_1 = plt.gcf();, ax_1 = plt.gca(); which are get current figure and get current axes redpectively. There are also multiple ways to change appearance, one for matlab
plt.make_current_axes_without_ticks( param)
and one for oop languages (
fig=plt.figure;
ax=fig.add_axes();
axis=ax.y_axis();
yticks=axis.ticks();
yticks.set_visible(false);
or smth like that.
Multiple interfaces sure make learning it harder, but it makes easier to transition from other similar tools and make it less rigid, meaning sometimes there're very simple ways to make frequently used but convoluted changes. (See ticks example)
I want to make an animated barchart in Python and save this animation in mp4 format. My problem is that the frames in the saved video overlay, although I use "blit=True" to tell the animation that only the things that change from frame to frame are drawn. Surprisingly, this problem does not occur in the built-in preview of Python.
Here is a minimal that reflects my situation:
import matplotlib.pyplot as plt
from matplotlib import animation
def barlist(n): #That's the list of bars I want to display
C=[]
for k in range(1,6):
C.append(1/float(n*k))
return C
fig=plt.figure()
n=100 #Number of frames
def animate(i):
x=range(1,6)
y=barlist(i+1)
return plt.bar(x,y)
anim=animation.FuncAnimation(fig,animate,repeat=False,blit=True,frames=n,
interval=50)
anim.save('barchart_animated_'+str(n)+'.mp4')
plt.show()
I must admit that I'm not pretty sure what I should do to remove this flaw. The only example I know of where the bars do not overlay in the frames is here (more exactly, I'm referring to the code of the first answer of the following link):
Dynamically updating a bar plot in matplotlib
It seems that I somehow have to tell the animation how it should set the height of each bar at each frame with the set_height-method. But as I said, I don't really know what's wrong in the above example. Thanks for any help!
Martin
The problem you have here is that you create a new barplot in every iteration of the animation. They will one by one be added to the plot, but since their height is shrinking over time, it may look as though only the first bar is present.
There are two ways to overcome this. First option is to clear the axes before plotting a new bar plot. This however will rescale the axis limits, which should then be constantly set to the same value.
The other option is to manipulate the one and only bar plot in the axes and adapt it's height for every frame. This is shown in the code below.
import matplotlib.pyplot as plt
from matplotlib import animation
def barlist(n):
return [1/float(n*k) for k in range(1,6)]
fig=plt.figure()
n=100 #Number of frames
x=range(1,6)
barcollection = plt.bar(x,barlist(1))
def animate(i):
y=barlist(i+1)
for i, b in enumerate(barcollection):
b.set_height(y[i])
anim=animation.FuncAnimation(fig,animate,repeat=False,blit=False,frames=n,
interval=100)
anim.save('mymovie.mp4',writer=animation.FFMpegWriter(fps=10))
plt.show()
Answers to the questions from the comments:
Blotting is a technique where all the parts of the figure which do not change are stored as a background. Then for each animated frame, only the changing parts are redrawn. This avoids the background to be redrawn from scratch and thus allows for much faster animations. Blitting will only affect the on-screen animation, because saving the animation to a file is not performed in real-time (and doesn't need to anyways).
Using blit=False here allows to make the code more simple because we do not need to care about the differences between the animation on screen and the one saved - they are just the same.
The enumerate function yields both the index as well as the object from the enumerated sequence. I did use it here, because it is a convenient way to obtain both in the same loop. It is not at all important here, you could alternatively do something like
for i in range(len(barcollection)):
barcollection[i].set_height(y[i])
I have created a little GUI with QT which set's up a single matplotlib figure and axes.
The GUI has controls to change just about everything to do with the appearance of the axes.
Basically, it does this by each widget emitting signals back up to the main frame and it calls the appropriate matplotlib setters on the axes and figure objects.
However, it is possible for the axes (and therefore the image displayed on the FigureCanvas) to change without input from the GUI (e.g. when autoscaling, or adding certain plots which adjust the axes automatically).
In this case, a widget controlling e.g. the limits of the x axis will now be displaying the wrong values.
I would like all the relevant widgets to update when the axes updates....how could I possible achieve this?
I'm thinking that this is a problem that has been solved before - how to enable a two-way communication between distinct objects?
fig.canvas.draw()
time.sleep(1e-2)
whenever anything writes to the plot? however it's hard to help with no code.
Showing an example of how your code is not working would help a lot.
EDIT:
I'll try this again then:
What about getting the state of the plot you are updating? I guess its what #Ajean means by updater method. I know that Artists in matplotlib have an Artist.properties() method that returns all of the properties and values.
I imagine Axes would have a similar method.
A quick look at the matplotlib docs yielded 2 interesting methods of axes:
ax.get_autoscale_on()
and
ax.set_autoscale_on().
ax.set_autoscale_on(False) will prevent plots from updating the state of the axes.
I am new to using PyLab. I want to plot some points. But I don't want to show the previous points i.e. as a new point comes the previous plotted point will vanish and the new point will be plotted. I have searched a lot but I could not find how to re-initialize the plot in between. The problem I am facing is I can set the current figure by using
plt.figure(f1.number) but after plotting the point in that figure it gets permanently changed.
plt.hold(False) before you start plotting will do what you want.
hold determines of old artists are held-on to when new ones are plotted. The default is for hold to be on.
ex
# two lines
plt.figure()
plt.hold(True)
plt.plot(range(5))
plt.plot(range(5)[::-1])
#one line
plt.figure()
plt.hold(False)
plt.plot(range(5))
plt.plot(range(5)[::-1])
Changing it via plt.hold changes it for all (new) axes. You can change the hold state for an individual axes by
ax = gca()
ax.hold(True)
With pylab, pylab.clf() should clear the figure, after which you can redraw the plot.
Alternatively, you can update your data with set_xdata and set_ydata that are methods on the axes object that gets returned when you create a new plot (either with pylab.plot or pylab.subplot).
The latter is probably preferred, but requires a litte more work. One example I can quickly find is another SO question.