I want to loop over a series of images to see how they change over time. Thus, I want them plotted on the same figure. The following code works but seems to slow down after a few iterations. Does anyone know why this is happening, how to overcome it, or an alternative way to visualize these images over time?
fig, ax=pyplot.subplots(figsize=(8,6))
for i in range(n):
ax.imshow(imageArray[i])
fig.canvas.draw()
time.sleep(0.2)
The animation is getting slower because the old image isn't deleted. More and more images will be redrawn each time you call fig.canvas.draw(). Therefore add ax.cla() before the imshow call. The tutorial that Jake suggested doesn't need the cla because it sets the image directly, and will therefore be slightly faster.
Related
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()
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 am working with a big set of data (240, 131000) and bigger. I am currently using the code below to plot this.
fig,ax = pyplot.subplots()
spectrum = ax.pcolor(waterfallplot, cmap='viridis')
pyplot.colorbar()
pyplot.show()
However, it's taking a very long time (30 min+) and the plot still hasn't shown up yet. A quick breakpoint check says the code gets to the spectrum= line, but doesn't go past. Looking at the memory on my computer, it hasn't even gotten close to the limit.
Does anyone have a better way of doing this?
pcolorfast works best for large arrays and updates quickly.
I'm working on an assignment which involves the need to show multiple figures on screen as the script is run (and also to save them). I am having to use both imshow and show to get the images up on the screen. This works fine, but I have read that show() should only be used once per script. Is there another way to display the image? The saved image files are also saving as blank 800x600 white images. Here's my code:
img = np.zeros((100,100))
plt.figure(0)
plt.imshow(img)
plt.show()
plt.savefig("images/img.png")
plt.close(0)
Each other figure is following the same syntax (obviously with different image names and a new figure number.
Thanks!
Generally, your approach using figure() to create a new figure object for each figure you want to display on the screen and save to a file is fine, if this is what you want to hear.
I'm not sure what your actual question is in this respect, so I would seriously recommend editing your question if there is something else you want to know.
Regarding the second issue: depending on the backend in use, show() may destroy objects in the figure (upon closing), which is why you generally should first savefig() and then show(). This is documented here.
I'm trying to animate a bunch of constantly updating points over an image (imagine making a plotted dot move diagonally across some image). I've looked at the animate examples here: http://matplotlib.org/examples/animation/dynamic_image.html, but I'm not sure how to keep the same image while clearing out all previous dots, then redrawing them. Any ideas?
You do not need to clear the figure between every frame
#initial data
ln, = ax.plot(x,y)
#...some loop code
ln.set_xdata(new_x)
ln.set_ydata(new_y)
Can you show some code of what you have tried, it will make it easier to give a more concrete answer.
Also see: using matplotlib's quiver in a loop efficiently, Visualization of 3D-numpy-array frame by frame