How do I get rid of attribute error in matplotlib animation - python

I want to turn a series of matplotlib figures into an animation. However, whatever I do, I always receive error. I use Enthought Canopy 1.6.2 and Python 2.7.13 on Windows 10.
I have tried using videofig package. While it was good, I could not manage to save the mp4 file. Also, I believe using the source directly, i.e., matplotlib animation package would be more versatile for future uses. I checked a few answers, including 1, 2 and 3, yet none of them solved my problem.
The function I call is structured as follows.
def some_plotter(self, path, start_value, image_array)
some_unrelated_fig_functions()
im=plt.savefig(path, animated=True)
image_array.append([im])
plt.close("all")
The main code is as follows:
import matplotlib.animation as animation
image_array=[]
while(something):
some_obj.some_plotter(path, start_value, image_array)
fig = plt.figure()
ani = animation.ArtistAnimation(fig, image_array, interval=50, blit=True, repeat_delay=1000)
I receive the following error:
Traceback (most recent call last):
File "C:\Users\kocac\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\cbook__init__.py", line 387, in process
proxy(*args, **kwargs)
File "C:\Users\kocac\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\cbook__init__.py", line 227, in call
return mtd(*args, **kwargs)
File "C:\Users\kocac\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\animation.py", line 1026, in _start
self._init_draw()
File "C:\Users\kocac\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\animation.py", line 1557, in _init_draw
artist.set_visible(False)
AttributeError: 'NoneType' object has no attribute 'set_visible'
I had more similar lines to this, yet updating Matplotlib, following the suggestion at 3 reduced the error lines to 4. Yet I cannot proceed any longer. Note that saved images are perfectly fine so I am probably not doing anything wrong in the image creation.
How can I get rid of these errors? Where am I going wrong?

Related

I cannot call show() after close() with matplotlib in python

I'm new to Python (I used MATLAB before), and I find that I cannot call show() after close some figures by close(). My goal is closing figures freely and then show the rest plots at last. Could anyone help me? Thank you.
My system: Python 3.6 on Windows 10. The matplotlib version is 2.2.2. I run my code through Eclipse.
Here is the code:
# Original code
import matplotlib.pyplot as plt
figA = plt.figure('aa')
figB = plt.figure('bb')
plt.close('aa')
plt.plot([2,3],[1,1],color='green')
plt.show()
When I run it, I get the following error in the Eclipse console.
Traceback (most recent call last):
File "D:\a project for testing dionysus\test_pythonPractice.py", line 26, in
plt.show()
File "C:\Users\hanlin\AppData\Local\Programs\Python\Python36\lib\site-packages\matplotlib\pyplot.py", line 253, in show
return _show(*args, **kw)
File "C:\Users\hanlin\AppData\Local\Programs\Python\Python36\lib\site-packages\matplotlib\backend_bases.py", line 208, in show
cls.mainloop()
File "C:\Users\hanlin\AppData\Local\Programs\Python\Python36\lib\site-packages\matplotlib\backends_backend_tk.py", line 1073, in mainloop
Tk.mainloop()
File "C:\Users\hanlin\AppData\Local\Programs\Python\Python36\lib\tkinter__init__.py", line 557, in mainloop
_default_root.tk.mainloop(n)
AttributeError: 'NoneType' object has no attribute 'tk'
However, if I change the code to either of the following two versions, there is no error.
# Revised ver.1
import matplotlib.pyplot as plt
figA = plt.figure('aa')
figB = plt.figure('bb')
plt.close('bb')
plt.plot([2,3],[1,1],color='green')
plt.show()
or
# Revised ver.2
import matplotlib.pyplot as plt
figA = plt.figure('aa')
figB = plt.figure('bb')
plt.close('aa')
plt.plot([2,3],[1,1],color='green')
plt.show(block=False)
plt.pause(3)
From revised ver.1, my guess is that close() only works on the last added figure. If we remove the previous figure, there will be an "empty" element in the list recording those figures. But this assumption violates the revised ver.2... Does anyone know why and how to solve this problem? Thank you.
Thanks to #Mr.T and #DavidG, I figure it out. Now the code becomes
# Revised original code
import matplotlib
matplotlib.use("Qt5Agg")
import matplotlib.pyplot as plt
figA = plt.figure('aa')
figB = plt.figure('bb')
plt.close('aa')
plt.plot([2,3],[1,1],color='green')
plt.show()
The culprit is the backend (default: "TkAgg"), and I set it as "Qt5Agg" now. I install the package pyqt5 by
pip install pyqt5==5.10.1
Note that the pyqt5 version needs to be 5.10.1. The latest one (5.11.2) would cause another error. For details, please read the webpage.

matplotlib error when running plotting in multiprocess

I am using python's Multiprocess.Pool to plot some data using multiple processes as follows:
class plotDriver:
def plot(self, parameterList):
numberOfWorkers = len(parameterList)
pool = Pool(numberOfWorkers)
pool.map(plotWorkerFunction, parameterList)
pool.close()
pool.join()
this is a simplified version of my class, the driver also contains other stuffs I choose to omit. The plotWorkderFunction is a single threaded function, which imports matplotlib and does all the plotting and setting figure styles and save the plots to one pdf file, and each worker is not interacting with the other.
I need to call this plot function multiple times since I have many parameterList, like following:
parameters = [parameterList0, parameterList1, ... parameterListn]
for param in parameters:
driver = PlotDriver()
driver.plot(param)
If parameters only contains one parameterList (the for loop only runs once), the code seems working fine. But it consistently fails whenever parameters contains more than one element, with the following error message happening on the second time in the loop.
Traceback (most recent call last):
File "plot.py", line 59, in <module>
plottingDriver.plot(outputFile_handle)
File "/home/yingryic/PlotDriver.py", line 69, in plot
pool.map(plotWrapper, workerParamList)
File "/home/yingryic/.conda/envs/pp/lib/python2.7/multiprocessing/pool.py", line 251, in map
return self.map_async(func.iterable, chunksize).get()
File "/home/yingryic/.conda/envs/pp/python2.7/multiprocessing/pool.py", line 567, in get
raise self._value
RuntimeError: In set_text: could not load glyph
X Error: BadIDChoice (invalid resouce ID chosen for this connection) 14
Extension: 138 (RENDER)
Minor opcode: 17 (RenderCreateGlyphSet)
Resouce id: 0xe00002
: Fatal IO error: client killed
any idea what is going wrong and how should I fix?
You can try placing import matplotlib into plotWorkerFunction() so that child processes will have their own copy of the module.

Python animation figure window cannot be closed automatically

When creating an animation using matplotlib.animation and saving it, an error appears when trying to close the figure window via plt.close:
Python version:
Python 2.7.12 |Anaconda custom (64-bit)| (default, Jul 2 2016, 17:42:40)
IPython 4.1.2 -- An enhanced Interactive Python
Currently I switched to using PyCharm 2017.1 Community Edition. The error message can be reproduced both directly in IPython and within PyCharm when running from %cpaste or %paste in IPython or running in PyCharm's interactive console using Shift+Alt+E. The movie encoder used is mencoder as integrated in mplayer, since this is the default one installed at my work place.
Note:
in IPython use plt.ion() first to turn on interactive mode (already switched on in PyCharm by default)
code exits without error in IPython when pasted using the middle mouse button directly into the IPython screen
code exits without error in IPython or PyCharm when typing all commands separately and also when pasting (%cpaste, %paste) all commands except for plt.close() and then typing plt.close() manually
code exits without error when replacing plt.close() with plt.clf(), but I need plt.close(), e.g. for creating animations in a loop with different parameters where the graph needs to be recreated from scratch
code exits without error when running the code in a script from start to end (non-interactive mode)
code exits without error when closing the figure window clicking with the mouse on the window button
code exits with error when inserting time.sleep(1) before plt.close(), so the problem likely does not relate to time conflicts in the code
A minimal, complete and (hopefully) verifiable example is given below:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
# animation function for random image data
def animate_random_data(i):
new_data = np.random.rand(10, 10)
# update the data
im.set_data(new_data)
# initialize the graph
first_data = np.random.rand(10,10)
im = plt.imshow(first_data,interpolation='none')
myfig = plt.gcf()
# create the animation and save it
ani = animation.FuncAnimation(myfig, animate_random_data, range(10),
interval=100)
ani.save('animation_random_data.mpg', writer='mencoder')
plt.close()
Error traceback (from PyCharm):
Traceback (most recent call last):
File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/backends/backend_qt5agg.py", line 176, in __draw_idle_agg
FigureCanvasAgg.draw(self)
File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/backends/backend_agg.py", line 474, in draw
self.figure.draw(self.renderer)
File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/artist.py", line 61, in draw_wrapper
draw(artist, renderer, *args, **kwargs)
File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/figure.py", line 1165, in draw
self.canvas.draw_event(renderer)
File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/backend_bases.py", line 1809, in draw_event
self.callbacks.process(s, event)
File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/cbook.py", line 563, in process
proxy(*args, **kwargs)
File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/cbook.py", line 430, in __call__
return mtd(*args, **kwargs)
File "/opt/local/anaconda/anaconda-2.2.0/lib/python2.7/site-packages/matplotlib/animation.py", line 652, in _start
self.event_source.add_callback(self._step)
AttributeError: 'NoneType' object has no attribute 'add_callback'
Although the program continues without error when closing the windows manually as written in the list above, it is an annoying bug (think of multiple animations in a loop). The error appears also for e.g. 1D line plots. Thanks for any help (and clarification on what this error message exactly means)!
The error comes from the animation still running while closing the figure. While in most cases it is automatically taken care of to stop the animation when closing the figure, it seems not to be the case in interactive mode.
A solution can be to explicitely stop the animation and delete it before closing the figure.
ani = animation.FuncAnimation(...)
ani.save(...)
ani.event_source.stop()
del ani
plt.close()
in this case you could just exit the program with exit()

Matplotlib: ion(): Why draw() for GTK3Agg but pause(s) for Qt4Agg?

I was trying to update a figure in matplotlib after each time step of a simulation.
I have managed to do this with:
import time, math
import matplotlib
matplotlib.use(u'Qt4Agg') # use some backend
# (c.f. http://stackoverflow.com/a/21836184 for .use())
import matplotlib.pyplot as plt
plt.ion()
fig = plt.figure()
sub = fig.add_subplot(1, 1, 1)
x = [i/100. for i in range(-500, 500)]
sin = lambda x : [math.sin(i) for i in x]
axis, = sub.plot(x, sin(x), 'r')
shift = 0.1
while shift < 5:
shift += 0.01
x = [i+shift for i in x]
axis.set_ydata(sin(x))
plt.pause(0.0001) # was plt.draw()
During the course of coming up with this solution I was almost getting mad because the Qt4Agg backend did now work properly with the draw() command where now there is a plt.pause(0.0001) command.
Now it works, but I get the following warning:
``/usr/local/lib/python2.7/dist-packages/matplotlib/backend_bases.py:2399: MatplotlibDeprecationWarning: Using default event loop until function specific to this GUI is implemented
warnings.warn(str, mplDeprecation)``
I also tried the GTK3Agg backend, but I am not sure if the computers where we want to run the project support it. Most surprisingly this backend worked with plt.draw() (except for the fact that the window freezes) but throws the following warnings and errors when running it with plt.pause(0.0001):
/usr/local/lib/python2.7/dist-packages/matplotlib/backend_bases.py:2399: MatplotlibDeprecationWarning: Using default event loop until function specific to this GUI is implemented
warnings.warn(str, mplDeprecation)
Traceback (most recent call last):
File "subplot_demo.py", line 24, in <module>
plt.pause(0.0001) # was plt.draw()
File "/usr/local/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 199, in pause
canvas.start_event_loop(interval)
File "/usr/local/lib/python2.7/dist-packages/matplotlib/backends/backend_gtk3.py", line 370, in start_event_loop
FigureCanvasBase.start_event_loop_default(self,timeout)
File "/usr/local/lib/python2.7/dist-packages/matplotlib/backend_bases.py", line 2407, in start_event_loop_default
self.flush_events()
File "/usr/local/lib/python2.7/dist-packages/matplotlib/backends/backend_gtk3.py", line 365, in flush_events
Gtk.main_iteration(True)
File "/usr/lib/python2.7/dist-packages/gi/types.py", line 43, in function
return info.invoke(*args, **kwargs)
TypeError: main_iteration() takes exactly 0 arguments (1 given)
I assume now that pause() is deprecated (as it proved also difficult to find some useful documentation about it) but still stick to it with the Qt4Agg backend as I am sure that PyQt4 will be installed on the target systems.
I now wonder: How do I correctly draw() with the Qt4Agg? The draw() call is not working, pause() deprecated - what can I do? (On a side note: What exactly went wrong in the pause()-call of the GTK3Agg backend?)
Some notes on versions:
Ubuntu: 12.04, Matplotlib: 1.4.3, Python: 2.7.3, GCC 4.6.3, PyQt: 4.8.1

Renderer problems using Matplotlib from within a script

I've narrowed down to this call:
fig.canvas.tostring_argb() #fig=matplotlib.pyplot.figure()
this function raises an AttributeError when I run the code as a python script.
AttributeError: 'FigureCanvasGTKAgg' object has no attribute 'renderer'
However, this code works properly if run in the ipython --pylab command line.
As far as I can tell from the documentation, the Agg renderer should work OK.
The context is that I'm trying to make a movie from figures, without saving the frames
to disk; as per this question. I'm using the approach that streams the pixel arrays
to ffmpeg (running as a separate process) to do this, I need the argb array of values from the frame.
Is there some configuration setting I can make to get matplotlib to work correctly from within a script?
Edit
Tried use('Agg') as per a comment; still fails; this is a minimal working example.
[dave#dave tools]$ python -c "import matplotlib; matplotlib.use('Agg'); import matplotlib.pyplot; fig=matplotlib.pyplot.figure(); fig.canvas.tostring_argb()"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/usr/lib64/python2.7/site-packages/matplotlib/backends/backend_agg.py", line 416, in tostring_argb
return self.renderer.tostring_argb()
AttributeError: FigureCanvasAgg instance has no attribute 'renderer'
I suspect that you have missed out the call to:
fig.canvas.draw()
before
fig.canvas.tostring_argb()
as
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot
fig=matplotlib.pyplot.figure()
fig.canvas.tostring_argb()
fails for me, but
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot
fig=matplotlib.pyplot.figure()
fig.canvas.draw()
fig.canvas.tostring_argb()
works.
I ended up installing and using the WXAgg backend; the Agg,and default GTKAgg, didn't work for me.

Categories