【问题标题】:Matplotlib error message: "TypeError: 'Ellipse' object is not iterable"Matplotlib 错误消息:“TypeError:'Ellipse' 对象不可迭代”
【发布时间】:2023-04-09 13:38:01
【问题描述】:

我尝试在 matplotlib (Python) animate 中运行动画,但出现错误

TypeError: 'Ellipse' object is not iterable

椭圆是“补丁”类型的对象...

结果是:

程序运行并生成第一个子图 - 它应该沿着读取的“线”移动椭圆......但是产生了上述错误消息。

现在错误消息是什么意思。

# -*- coding: utf-8 -*-
#############################################################################
#   first try to compute the program for demonstrating the dependency of
#   total annual insolation of a planet (here Earth) on the ellipticity of 
#   the orbit
#
#############################################################################
#   created 2015-06-01 by Jörg Kampmann - IBK-consult - D-31228 Peine
#
#############################################################################
#   the insolation 
#   N_EGA = (2*pi**2*R**2*N0)/(n*a**2*sqrt(1 - e**2))
#   is dependent on "e" under the assumption that "a" and "N0" are constant
#
#   this module 
#   computes and shows presently the dependency of TOI over e
#
#   Todo: animation of size of ellipse when eccentricity grows from zero to 
#   ECCmax
#
#############################################################################
#Path to the workbook datasets
#datapath = '/home/kampmann/rtpSW/WorkbookDatasets/'
#Path to the hitran by-molecule database
#hitranPath = datapath+'Chapter4Data/hitran/ByMolecule/'

"""
Excentricity is ECC = sqrt(a**2 - b**2) or
ECC**2 = a**2 - b**2
b**2 = a**2 - ECC**2
b = sqrt(a**2 - ECC**2)
a = height/2.0
->
b = sqrt(height**2/4.0 - ECC**2)
"""

import math
from ClimateUtilities import *
import phys
import numpy as nm
import matplotlib.animation as animation
import matplotlib.pyplot as plt
from matplotlib import patches
#from matplotlib import animation


#------------Constants and file data------------
# eccentricity
printswitch = True
printswitch = False
printswitch2 = True
#printswitch2 = False

ECCabsoluteMax = 0.9
ECCmax = 0.067      # maximum value for this run - should not be greater than
                    # ECCabsoluteMax
#ECCmax = 0.9      # maximum value for this run - should not be greater than
                    # ECCabsoluteMax
if ECCmax >= ECCabsoluteMax: 
    ECCmax = ECCabsoluteMax

ECCdelta = 0.001    # interval for graph

eccentricity = nm.arange(0., ECCmax, ECCdelta, dtype=float)
semimajorA = 1.0        # astronomical unit =~ 150.000.000 km mean distance Sun Earth
totalRadN0 = 1370.      # radiation of Sun at TOA in Watt/m**2
albedoEarth = 0.3       # presently albedo of Earth, geographically constant
T = 365.25              # duration of one orbit around central celestial body in days
                        # here: duration of one orbit of Earth around Sun
R = 6378100.0           # radius of Earth in meters

TOIdim = ECCmax/ECCdelta
TOI =nm.arange(0., TOIdim, dtype=float ) 
                        # total insolation at location of Earth summed over 1 year

"""
now define various "functions" like:
"""
def computeTOI( ee, semimajorAxis, radiationAtStar, alpha  ):

    aa = semimajorAxis  # semimajor axis of orbital ellipse
    N0 = radiationAtStar# radiation of start at position of star (r = 0)
    resultTOI = 2.*nm.pi*T*R**2*N0*alpha/(aa**2*math.sqrt(1 - ee**2))
    return resultTOI

def init_TOI():
    line1.set_data([], [])
    return line1

def init_Ellipse():
    line2.set_data([], [])
    return line2

def animateTOI():

    return True
#
#####################################################################
#
print "start of ellipticity and absorbed insolation"
#
#
# Start of programme here
#
#####################################################################

# compute the various TOIs dependant on eccentricity "ecc"
#
ii = 0
for ecc in eccentricity:
    if printswitch:   print 'TOI = ', computeTOI( ecc, semimajorA, totalRadN0, albedoEarth ), '\n'
    TOI[ii] = computeTOI( ecc, semimajorA, totalRadN0, 1. - albedoEarth )/10.0**19
    ii = ii + 1

# TOI is an array consisting of TOIs depending on eccemtricity "ecc" 

x = eccentricity
if printswitch: print 'TOI = ', TOI

#print 'ECC = ', x

# almost the whole screen is filled with this plot ... :)
Main = plt.figure(figsize=(15.0,15.0))  
Main.subplots_adjust(top=0.95, left=0.09, right=0.95, hspace=0.20)

axFigTOI = Main.add_subplot(211)

# Plot ... TOI over ECC: 

if ECCmax < 0.07: 
    plt.axis([0,0.07,8.9,9.0]) 

plt.title( 'Absorbed Irradiation and Orbital Eccentricity for Planet Earth\n' )
plt.ylabel( 'Absorbed total \nsolar irradiation \n[Watt] *10**19' )
plt.xlabel( 'Eccentricity "e"' )

plt.plot( x, TOI, 'r-' )  # this works fine! 'x' and 'TOI' are center of mini-ellipse

# Now enter an ellipse here on Subplot 211:

xcenter, ycenter = x[1],TOI[1]      # center of ellipse to start with
width = 0.0025
height = 0.01


e1 = patches.Ellipse((xcenter, ycenter), width, height,\
            angle=0.0, linewidth=2, fill=True, zorder=2)
e1.set_visible(True)
axFigTOI.add_patch( e1 )

def init():
    axFigTOI.add_patch(e1)
    return e1

def animateEllipse(i):

    xcenter = x[i]
    ycenter = TOI[i]
    e1 = patches.Ellipse((xcenter, ycenter), width, height,\
             angle=0.0, linewidth=2, fill=True, zorder=2)
    if i == 1:
        e1.set_visible(True)

    axFigTOI.add_patch(e1)

    return e1

anim = animation.FuncAnimation(Main, animateEllipse, 
                               init_func=init, 
                               frames=360, 
                               interval=20,
                               blit=True)

plt.show()





---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/home/kampmann/Enthought/Canopy_32bit/User/lib/python2.7/site-packages/matplotlib/backends/backend_qt5.pyc in resizeEvent(self=<matplotlib.backends.backend_qt4agg.FigureCanvasQTAgg object>, event=<0xbf9f7b48 >)
    336         self.figure.set_size_inches(winch, hinch)
    337         FigureCanvasBase.resize_event(self)
--> 338         self.draw()
        self.draw = <bound method FigureCanvasQTAgg.draw of <matplotlib.backends.backend_qt4agg.FigureCanvasQTAgg object at 0xb0eef26c>>
    339         self.update()
    340         QtWidgets.QWidget.resizeEvent(self, event)

/home/kampmann/Enthought/Canopy_32bit/User/lib/python2.7/site-packages/matplotlib/backends/backend_qt5agg.pyc in draw(self=<matplotlib.backends.backend_qt4agg.FigureCanvasQTAgg object>)
    146         # causes problems with code that uses the result of the
    147         # draw() to update plot elements.
--> 148         FigureCanvasAgg.draw(self)
        global FigureCanvasAgg.draw = <unbound method FigureCanvasAgg.draw>
        self = <matplotlib.backends.backend_qt4agg.FigureCanvasQTAgg object at 0xb0eef26c>
    149         self._priv_update()
    150 

/home/kampmann/Enthought/Canopy_32bit/User/lib/python2.7/site-packages/matplotlib/backends/backend_agg.pyc in draw(self=<matplotlib.backends.backend_qt4agg.FigureCanvasQTAgg object>)
    467 
    468         try:
--> 469             self.figure.draw(self.renderer)
        self.figure.draw = <bound method Figure.draw of <matplotlib.figure.Figure object at 0xb100896c>>
        self.renderer = <matplotlib.backends.backend_agg.RendererAgg object at 0xb117bbec>
    470         finally:
    471             RendererAgg.lock.release()

/home/kampmann/Enthought/Canopy_32bit/User/lib/python2.7/site-packages/matplotlib/artist.pyc in draw_wrapper(artist=<matplotlib.figure.Figure object>, renderer=<matplotlib.backends.backend_agg.RendererAgg object>, *args=(), **kwargs={})
     57     def draw_wrapper(artist, renderer, *args, **kwargs):
     58         before(artist, renderer)
---> 59         draw(artist, renderer, *args, **kwargs)
        global draw = undefined
        artist = <matplotlib.figure.Figure object at 0xb100896c>
        renderer = <matplotlib.backends.backend_agg.RendererAgg object at 0xb117bbec>
        args = ()
        kwargs = {}
     60         after(artist, renderer)
     61 

/home/kampmann/Enthought/Canopy_32bit/User/lib/python2.7/site-packages/matplotlib/figure.pyc in draw(self=<matplotlib.figure.Figure object>, renderer=<matplotlib.backends.backend_agg.RendererAgg object>)
   1089         self._cachedRenderer = renderer
   1090 
-> 1091         self.canvas.draw_event(renderer)
        self.canvas.draw_event = <bound method FigureCanvasQTAgg.draw_event of <matplotlib.backends.backend_qt4agg.FigureCanvasQTAgg object at 0xb0eef26c>>
        renderer = <matplotlib.backends.backend_agg.RendererAgg object at 0xb117bbec>
   1092 
   1093     def draw_artist(self, a):

/home/kampmann/Enthought/Canopy_32bit/User/lib/python2.7/site-packages/matplotlib/backend_bases.pyc in draw_event(self=<matplotlib.backends.backend_qt4agg.FigureCanvasQTAgg object>, renderer=<matplotlib.backends.backend_agg.RendererAgg object>)
   1793         s = 'draw_event'
   1794         event = DrawEvent(s, self, renderer)
-> 1795         self.callbacks.process(s, event)
        self.callbacks.process = <bound method CallbackRegistry.process of <matplotlib.cbook.CallbackRegistry instance at 0xb0e3814c>>
        s = u'draw_event'
        event = <matplotlib.backend_bases.DrawEvent instance at 0xb0ebebac>
   1796 
   1797     def resize_event(self):

/home/kampmann/Enthought/Canopy_32bit/User/lib/python2.7/site-packages/matplotlib/cbook.pyc in process(self=<matplotlib.cbook.CallbackRegistry instance>, s=u'draw_event', *args=(<matplotlib.backend_bases.DrawEvent instance>,), **kwargs={})
    538                     del self.callbacks[s][cid]
    539                 else:
--> 540                     proxy(*args, **kwargs)
        proxy = <matplotlib.cbook._BoundMethodProxy object at 0xb0fdfb2c>
        args = (<matplotlib.backend_bases.DrawEvent instance at 0xb0ebebac>,)
        kwargs = {}
    541 
    542 

/home/kampmann/Enthought/Canopy_32bit/User/lib/python2.7/site-packages/matplotlib/cbook.pyc in __call__(self=<matplotlib.cbook._BoundMethodProxy object>, *args=(<matplotlib.backend_bases.DrawEvent instance>,), **kwargs={})
    413             mtd = self.func
    414         # invoke the callable and return the result
--> 415         return mtd(*args, **kwargs)
        mtd = <bound method ?._end_redraw of <matplotlib.animation.FuncAnimation object at 0xb0fdf44c>>
        args = (<matplotlib.backend_bases.DrawEvent instance at 0xb0ebebac>,)
        kwargs = {}
    416 
    417     def __eq__(self, other):

/home/kampmann/Enthought/Canopy_32bit/User/lib/python2.7/site-packages/matplotlib/animation.pyc in _end_redraw(self=<matplotlib.animation.FuncAnimation object>, evt=<matplotlib.backend_bases.DrawEvent instance>)
    879         # Now that the redraw has happened, do the post draw flushing and
    880         # blit handling. Then re-enable all of the original events.
--> 881         self._post_draw(None, self._blit)
        self._post_draw = <bound method FuncAnimation._post_draw of <matplotlib.animation.FuncAnimation object at 0xb0fdf44c>>
        global None = undefined
        self._blit = True
    882         self.event_source.start()
    883         self._fig.canvas.mpl_disconnect(self._resize_id)

/home/kampmann/Enthought/Canopy_32bit/User/lib/python2.7/site-packages/matplotlib/animation.pyc in _post_draw(self=<matplotlib.animation.FuncAnimation object>, framedata=None, blit=True)
    825         # blitting.
    826         if blit and self._drawn_artists:
--> 827             self._blit_draw(self._drawn_artists, self._blit_cache)
        self._blit_draw = <bound method FuncAnimation._blit_draw of <matplotlib.animation.FuncAnimation object at 0xb0fdf44c>>
        self._drawn_artists = <matplotlib.patches.Ellipse object at 0xb0fdf80c>
        self._blit_cache = {}
    828         else:
    829             self._fig.canvas.draw_idle()

/home/kampmann/Enthought/Canopy_32bit/User/lib/python2.7/site-packages/matplotlib/animation.pyc in _blit_draw(self=<matplotlib.animation.FuncAnimation object>, artists=<matplotlib.patches.Ellipse object>, bg_cache={})
    834         # of the entire figure.
    835         updated_ax = []
--> 836         for a in artists:
        a = undefined
        artists = <matplotlib.patches.Ellipse object at 0xb0fdf80c>
    837             # If we haven't cached the background for this axes object, do
    838             # so now. This might not always be reliable, but it's an attempt

TypeError: 'Ellipse' object is not iterable

【问题讨论】:

  • 当您发布错误消息时,请发布整个错误消息,包括堆栈跟踪。
  • 抱歉,我是故意这样做的,因为错误跟踪消息非常长。但我会更进一步地输入它 - 虽然我不知道如何从“enthought-console”输出中复制它 - 似乎很难......所以请耐心等待......
  • 错误处理完成......这并不难:)

标签: python matplotlib error-handling runtime-error enthought


【解决方案1】:

来自FuncAnimation 的 matplotlib 文档:

如果 blit=True,func 和 init_func 应该返回一个可迭代的可绘制对象来清除。

您返回的是单个 Ellipse,而不是可迭代的可绘制对象。

【讨论】:

  • Thnx:我理解你的意思,但是:如何使 Ellipse 可迭代?我在文档中没有找到任何相关内容!也不在“补丁”的文档中:)
  • @kampmannpeine:很可能,你没有;你返回别的东西。我对 matplotlib 不够熟悉,不知道 Ellipse 是否算作您想要清除的可绘制对象,但我猜如果您不想清除任何内容或 @ 987654324@如果你想清除椭圆。
  • tnx:这让我在涅槃;) - 但是!
  • 从 Python 聊天室我得到了解决方案......就像 user2357112 建议的那样:将 e1 设为列表:[e1] 并将其放入 FuncAnimation 的返回值中......无论如何,谢谢......
  • 谢谢!我对Axes3DSubplot 有同样的问题。 TypeError: 'Axes3DSubplot' object is not iterable
【解决方案2】:

要返回可迭代的'Ellipse',您必须在返回e1 时加上逗号。所以,init()animateEllipse(i) function: "return e1," 都必须加逗号

【讨论】:

    猜你喜欢
    • 2012-03-26
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 2018-08-17
    • 2020-11-28
    • 1970-01-01
    • 2013-09-01
    相关资源
    最近更新 更多