FuncAnimation does not refresh - matplotlib

I am having problems with FuncAnimation, I am using a slightly modified example http://matplotlib.org/examples/animation/basic_example.html
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def update_line(num, data, line):
data.pop(0)
data.append(np.random.random())
line.set_ydata(data)
return line,
fig1 = plt.figure()
data = [0.0 for i in xrange(100)]
l, = plt.plot(data, 'r-')
plt.ylim(-1, 1)
line_ani = animation.FuncAnimation(fig1, update_line, 25, fargs=(data, l), interval=50, blit=True)
plt.show()
The problem is that the first line (updated by update_line) stays in background.
If I resize the window (click on the corner of the window and moving the mouse). This first line disappears but now the first line after the resize stays in background.
Is this normal, or I am doing something wrong.
Thanks in advance

If you are not overly worried about speed, remove blit=True and it should work.
Blitting is a way to save time by only re-drawing the bits of the figure that have changed (instead of everything), but is easy to get messed up. If you do not include blit=True all the artists get re-drawn every time.
I recommend reading python matplotlib blit to axes or sides of the figure? and Animating Matplotlib panel - blit leaves old frames behind.

Related

How to fix lines of axes overlapping imshow plot?

When plotting matrices using matplotlib's imshow function the lines of the axes can overlap the actual plot, see the following minimal example (matshow is just a simple wrapper around imshow):
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(3,3))
ax.matshow(np.random.random((50, 50)), interpolation="none", cmap="Blues")
plt.savefig("example.png", dpi=300)
I would expect every entry of the matrix to be represented by a square, but in the top row it is quite obvious that the axis is hiding a bit of the plot resulting in non-square entries. The same is happening for the last column. Since I want the complete matrix to be seen - every entry with the same importance - is there any way this can be fixed?
To me, this is just a visualisation issue. If I run your code and maximise the window, I do not see the overlapping you are talking about:
Otherwise, remove the spines but without hiding the ticks:
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
EDIT
Reduce the thickness of the borders:
[x.set_linewidth(0.3) for x in ax.spines.values()]
The following is the exported image:
With 0.2 the exported image looks like this:

how to make plt plot do not show figure [duplicate]

I need to create a figure in a file without displaying it within IPython notebook. I am not clear on the interaction between IPython and matplotlib.pylab in this regard. But, when I call pylab.savefig("test.png") the current figure get's displayed in addition to being saved in test.png. When automating the creation of a large set of plot files, this is often undesirable. Or in the situation that an intermediate file for external processing by another app is desired.
Not sure if this is a matplotlib or IPython notebook question.
This is a matplotlib question, and you can get around this by using a backend that doesn't display to the user, e.g. 'Agg':
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.savefig('/tmp/test.png')
EDIT: If you don't want to lose the ability to display plots, turn off Interactive Mode, and only call plt.show() when you are ready to display the plots:
import matplotlib.pyplot as plt
# Turn interactive plotting off
plt.ioff()
# Create a new figure, plot into it, then close it so it never gets displayed
fig = plt.figure()
plt.plot([1,2,3])
plt.savefig('/tmp/test0.png')
plt.close(fig)
# Create a new figure, plot into it, then don't close it so it does get displayed
plt.figure()
plt.plot([1,3,2])
plt.savefig('/tmp/test1.png')
# Display all "open" (non-closed) figures
plt.show()
We don't need to plt.ioff() or plt.show() (if we use %matplotlib inline). You can test above code without plt.ioff(). plt.close() has the essential role. Try this one:
%matplotlib inline
import pylab as plt
# It doesn't matter you add line below. You can even replace it by 'plt.ion()', but you will see no changes.
## plt.ioff()
# Create a new figure, plot into it, then close it so it never gets displayed
fig = plt.figure()
plt.plot([1,2,3])
plt.savefig('test0.png')
plt.close(fig)
# Create a new figure, plot into it, then don't close it so it does get displayed
fig2 = plt.figure()
plt.plot([1,3,2])
plt.savefig('test1.png')
If you run this code in iPython, it will display a second plot, and if you add plt.close(fig2) to the end of it, you will see nothing.
In conclusion, if you close figure by plt.close(fig), it won't be displayed.

Fast image sequences / animation in Jupyter Notebook with matplotlib

I can't seem to find a simple and fast way of plotting image sequences with plain matplotlib in a Jupyter Notebook. I've tried FuncAnimation, fig.canvas.draw(), blitting, as well as just the standard imshow-pause combo; without success or with very slow refresh rate. I don't need the images to be interactive - they just need to be shown sequentially and can't pop up a new figure window for each image. I've seen many solutions here, with none seeming to work the way I want.
My general pipeline does significant processing, with each image generated and plotted within a while or for loop. FuncAnimation is not desirable since it requires passing a function handle and my use case involves many arguments and state variables that make it difficult to use.
The best I've got is the working example below using fig.canvas.draw() - showing that drawing time increases linearly per iteration, where I need it to remain constant!
import numpy as np
import matplotlib.pyplot as plt
from timeit import default_timer as timer
%matplotlib notebook
num_iters = 50
im = np.arange(60).reshape((15,4))
fig, ax = plt.subplots(1,1)
fig.show()
fig.canvas.draw()
iter_times = np.zeros(num_iters)
for i in range(num_iters):
im = np.roll( a=im, shift=1, axis=0 )
t0 = timer()
ax.imshow(im.T, vmin=im.min(), vmax=im.max())
ax.set_title('Iter # {}/{}'.format(i+1, num_iters))
fig.canvas.draw()
iter_times[i] = timer()-t0
plt.figure(figsize=(6,3))
plt.plot(np.arange(num_iters)+1, iter_times)
plt.title('Imshow/drawing time per iteration')
plt.xlabel('Iteration number')
plt.ylabel('Time (seconds)')
plt.tight_layout()
plt.show()
I think the problem is that the plots are 'building up', so every one is being plotted every time. If you add ax.clear() right before the imshow(), you'll get linear plot times.

How do I set the resize-behaviour of subplots?

I'm working with several subplots in a window. Just after plotting it looks great, problem is when I rezise the windows manually. The subplots do not adapt correctly to the new size of the window. How can I fix that?
Window after plotting, looking great:
window after resizing it manually, looks bad:
EDIT:
A simply demo-Code:
from matplotlib.pyplot import *
figure(figsize=(24,6))
subplot(131)
ylabel("test")
plot([1,2,3], label="test1")
plot([3,2,1], label="test2")
subplot(132)
ylabel("test")
plot([1,2,3], label="test1")
plot([3,2,1], label="test2")
subplot(133)
ylabel("test")
plot([1,2,3], label="test1")
plot([3,2,1], label="test2")
tight_layout()
show()
As you see, the plot looks good after plotting it. But when you start to shrink the plot horizontally, the space between plot and plot gets smaller and smaller. And at the end, the ticklabels are on others plots, because there's no space for them. I need to know how to set that the entire plot gets smaller, leving space for the labels.
Maybe not exactly the answer of my question, but it solves my problem:
After creating the figure, you connect the resize-event to an eventhandler:
cid = fig.canvas.mpl_connect('resize_event', onresize)
def onresize(event):
plt.tight_layout()
As Wicket said, I'm just calling tight_layout() again and again, but automatically.

Calling pylab.savefig without display in ipython

I need to create a figure in a file without displaying it within IPython notebook. I am not clear on the interaction between IPython and matplotlib.pylab in this regard. But, when I call pylab.savefig("test.png") the current figure get's displayed in addition to being saved in test.png. When automating the creation of a large set of plot files, this is often undesirable. Or in the situation that an intermediate file for external processing by another app is desired.
Not sure if this is a matplotlib or IPython notebook question.
This is a matplotlib question, and you can get around this by using a backend that doesn't display to the user, e.g. 'Agg':
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.savefig('/tmp/test.png')
EDIT: If you don't want to lose the ability to display plots, turn off Interactive Mode, and only call plt.show() when you are ready to display the plots:
import matplotlib.pyplot as plt
# Turn interactive plotting off
plt.ioff()
# Create a new figure, plot into it, then close it so it never gets displayed
fig = plt.figure()
plt.plot([1,2,3])
plt.savefig('/tmp/test0.png')
plt.close(fig)
# Create a new figure, plot into it, then don't close it so it does get displayed
plt.figure()
plt.plot([1,3,2])
plt.savefig('/tmp/test1.png')
# Display all "open" (non-closed) figures
plt.show()
We don't need to plt.ioff() or plt.show() (if we use %matplotlib inline). You can test above code without plt.ioff(). plt.close() has the essential role. Try this one:
%matplotlib inline
import pylab as plt
# It doesn't matter you add line below. You can even replace it by 'plt.ion()', but you will see no changes.
## plt.ioff()
# Create a new figure, plot into it, then close it so it never gets displayed
fig = plt.figure()
plt.plot([1,2,3])
plt.savefig('test0.png')
plt.close(fig)
# Create a new figure, plot into it, then don't close it so it does get displayed
fig2 = plt.figure()
plt.plot([1,3,2])
plt.savefig('test1.png')
If you run this code in iPython, it will display a second plot, and if you add plt.close(fig2) to the end of it, you will see nothing.
In conclusion, if you close figure by plt.close(fig), it won't be displayed.