从这里开始:
Animation using matplotlib with subplots and ArtistAnimation
我对我的问题有一些暗示 - 但还不够。我的问题:
我有两个动画都以某种方式耦合,并希望在不同的子图中显示它们。
第一个子图中的第一个动画效果很好 - 但是第二个子图中的第二个(第一个)动画只会影响第一个动画......
那么如何以第二个子情节 NOT 影响第一个子图的方式解耦子图:
这是示例的代码:
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------------
#
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
deltaT = 500 # ms interval of moving
# 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
#
#####################################################################
#
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
##########################################################################
# 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) # first subplot
# 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-' ) # 'x' and 'TOI' are also center of "mini-
# ellipse"
# Now enter an ellipse here on Subplot 211 (first subplot) which slides
# along curve:
xcenter, ycenter = x[1],TOI[1] # center of ellipse to start with
width = 0.0025 # width of small ellipse
height = 0.01 # height of small ellipse
def init(): # in order to initialize animation
e1 = patches.Ellipse((xcenter, ycenter), width, height,\
angle=0.0, linewidth=2, fill=False )
axFigTOI.add_patch(e1)
e1.set_visible( False ) # do not show (if True then ellipse
# stays here
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 )
if i == 1:
e1.set_visible( True )
axFigTOI.add_patch(e1)
if printswitch: print 'i = ', i
return [e1]
anim = animation.FuncAnimation( Main,
animateEllipse,
init_func=init,
frames= int( TOIdim ),
interval=deltaT,
blit=True )
#########################################################################
# the second subplot in the first figure for size of ellipse depending on
# ECC
#########################################################################
# we still have a problem to get the "patch" (Ellipse) into the 2nd
# subplot ...
axFigEllipse = Main.add_subplot(212)
plt.title( 'Shape of an Ellipse due to eccentricity' )
plt.ylabel( 'Height of Ellipse' )
plt.xlabel( 'Constant Semi-major Axis' )
"""
#
# create an ellipse with following parameters - to be changed later for
# curve
# values
#
xcenter2 = x[40]
ycenter2 = TOI[40] # center of ellipse 2 to start with
width2 = 0.0125
height2 = 0.0115
ell2 = patches.Ellipse( ( xcenter2, ycenter2 ), width2, height2,\
angle=0.0, linewidth=2, fill=False )
ell2.set_visible(True)
axFigEllipse.add_patch(ell2)
#"""
"""
def init212(): # in order to initialize animation
ell2 = patches.Ellipse((xcenter2, ycenter2), width2, height2,\
angle=0.0, linewidth=2, fill=False )
axFigEllipse.add_patch(ell2)
ell2.set_visible( False ) # do not show (if True then ellipse
# stays here
return [ell2]
def animateEllipse(jj):
#xcenter2 = xcenter2 + jj/10**4
#ycenter2 = ycenter2 + jj/10**4
ell2 = patches.Ellipse((xcenter2, ycenter2), width2, height2,\
angle=0.0, linewidth=2, fill=True, zorder=2)
if jj == 1:
ell2.set_visible(True)
axFigEllipse.add_patch(ell2)
return [ell2]
anim = animation.FuncAnimation( Main, animateEllipse,
init_func=init212,
frames=360,
interval=20,
blit=True )
#anim = animation.FuncAnimation(figEllipse, animateEllipse,
init_func=init_Ellipse, interval=1, blit=True)
#"""
plt.show()
现在当我删除“”时,只有红线可见......没有活动......
答案 0 :(得分:1)
在您的代码中,您基本上会在以后重新定义animateEllipse
。您应该只在脚本中调用单个动画,该脚本应更新两个省略号(从对象返回两个句柄)。为了调整大小,您可以使用现有的椭圆形手柄,但移动似乎需要添加一个新的椭圆。我无法让你的代码工作,但作为一个最小的例子,一个更新所有子图的函数(这些子图各自可以在它们自己的函数中)。
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from matplotlib import animation
import numpy as np
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.5, angle=0)
e2 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.5, angle=0)
ax1.add_patch(e1)
ax2.add_patch(e2)
def init():
e1.set_visible(False)
e2.set_visible(False)
return e1,e2
def animateEllipse211(i):
e1 = Ellipse(xy=(0.5+0.2*np.sin(i/200.), 0.5+0.2*np.sin(i/200.)), width=0.5, height=0.5, angle=0)
ax1.add_patch(e1)
if i==0:
e1.set_visible(True)
return e1
def animateEllipse212(i):
if i==0:
e2.set_visible(True)
e2.width = 0.5*np.sin(i/200.)
e2.height = 0.5*np.sin(i/200.)
return e2
def animate(i):
e1 = animateEllipse211(i)
e2 = animateEllipse212(i)
return e1,e2
anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()
更新:我不确定为什么会出现这个奇怪的init
问题,但认为在其他一些帖子(this和this)上已经注意到了使用blit=True
。 matplotlib上的动画在边缘有点粗糙,当然不是很直观。更糟糕的是,后端的选择(即绘制实际数据的内容)会对其工作方式产生影响。我个人通常会运行循环,使用交互模式并在需要视频时保存数字。
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
import numpy as np
#Setup figure, add subplots and ellipses
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.5, angle=0)
e2 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.5, angle=0)
ax1.add_patch(e1)
ax2.add_patch(e2)
#Plot Red line
ax1.plot(np.linspace(.3,.7,100),np.linspace(.3,.7,100),'r-')
#Turn on interactive plot
plt.ion()
plt.show()
#Define a loop and update various
for i in range(0, 10000, 10):
print(i)
#Update ellipse 1
e1.remove()
e1 = Ellipse(xy=(0.5+0.2*np.sin(i/200.),
0.5+0.2*np.sin(i/200.)),
width=0.5, height=0.5, angle=0)
ax1.add_patch(e1)
#Update ellipse 2
e2.width = 0.5*np.sin(i/200.)
e2.height = 0.5*np.sin(i/200.)
plt.draw()
plt.pause(0.0001)