我只是在玩 matplotlib 的影片模塊。我想創建一個彈丸運動的影片情節。我設法使用以下代碼創建它:

import matplotlib.animation as ani
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['figure.dpi'] = 150
## Inputs
angle = 30 # deg
angleRad = angle*np.pi/180
vel = 2 # m/s
deltat = 0.005 # s (timestep)
acc = -9.81 # m/s^2 (gravitational acc)
## Calculations
# Initialisations
ux0 = vel*np.cos(angleRad)
uy0 = vel*np.sin(angleRad)
U = [ux0]
V = [uy0]
# Acceleration
ax = 0
ay = acc
# Velocity
def calcVel(time):
Uvel = ux0 ax*time
Vvel = uy0 ay*time
return (Uvel, Vvel)
# Location
x0 = 0
y0 = 0
x = [x0]
y = [y0]
def location(time):
locx = U[0]*time 0.5*ax*time**2
locy = V[0]*time 0.5*ay*time**2
return (locx, locy)
yn = y0
t0 = 0
n = 1
count = [0]
while yn>=0:
t = t0 n*deltat
xVel, yVel = calcVel(t)
posx, posy = location(t)
yn = posy
if yn>=0:
U.append(xVel)
V.append(yVel)
x.append(posx)
y.append(posy)
count.append(t)
n =1
def buildframes(i=int):
line.set_data(x[:i], y[:i])
points.set_offsets([x[i-1], y[i-1]])
index.set_text('time = %.3f s' % count[i])
plt.pause(0.001)
## Plotting
fig = plt.figure()
axes = fig.add_subplot(1,1,1)
line, = axes.plot([], []) # , 'bo', lw=2, scalex = True, scaley = True
points = plt.scatter([], [], c='red', s=15)
axes.set_ylim(min(y), np.true_divide(np.ceil(max(y) * 10**2), 10**2))
axes.set_xlim(min(x), np.true_divide(np.ceil(max(x) * 10**2), 10**2))
plt.ylabel('Height')
plt.xlabel('Distance')
index = axes.annotate('', xy=(0.75, 0.95), xycoords='axes fraction')
animator = ani.FuncAnimation(fig, buildframes, interval = 500)
#animator.save("filename")
plt.show()
animator.save('animation.gif')
標題問題很容易成為一個通用的“我如何改進此代碼”,但這里不鼓勵這樣做。雖然代碼生成影片,但此代碼存在幾個更精細的問題。我按重要性降序列出了它們:
- “串列索引超出范圍”錯誤:這是由于繪制線和散點的方式造成的。對于線,應該已經有兩個點了。如何避免這種情況并擁有更清潔的影片師功能?(它仍然在繪圖 - 只是這個錯誤仍然存??在,這讓我很煩。)
- 線尖總是在點上(注意紅球上的藍色小線段)。我試圖改變順序,但這無助于讓紅點始終在線上。我該怎么做?
- 在 Spyder 中運行時,它似乎在繪圖視窗中對其進行了兩次影片處理(速度不同)。我不確定為什么。創建的 gif 始終以較晚的速度(較慢)。保存時可能會覆寫速度較慢的幀,從而覆寫觀察結果。這意味著影片器函式被呼叫了兩次?我該如何解決?如果我在 Linux python 環境中運行它就不會發生這種情況。
- Generic:有沒有更聰明的方法來做同樣的影片?例如,我覺得代碼太長了,有什么方法可以使它更緊湊,或許更高效?
uj5u.com熱心網友回復:
- 將影片中的幀數設定為等于您正在繪制的變數的長度。例如:
ani.FuncAnimation(fig, buildframes, frames=len(x), interval=500) - 您可以使用
zorder強制以適當的順序顯示事物。在這里,我使用“zorder=1for the line andzorder=2”作為散點圖,因此散點圖將顯示在行的頂部。 - 我無法對此發表評論,因為我不使用 Spyder。
- 使用影片時,不要放在
plt.pause影片函式中。interval呼叫時設定適當的ani.FuncAnimation。影片功能本來就很好。在下面的代碼中,我使用 Numpy 的“矢量化”完成了相同的計算,因此無需使用回圈(這節省了一些代碼行)。
import matplotlib.animation as ani
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['figure.dpi'] = 150
## Inputs
angle = 30 # deg
angleRad = angle*np.pi/180
vel = 2 # m/s
deltat = 0.005 # s (timestep)
acc = -9.81 # m/s^2 (gravitational acc)
# Initialisations
x0 = 0
y0 = 0
ux0 = vel*np.cos(angleRad)
uy0 = vel*np.sin(angleRad)
ax = 0
ay = acc
# https://stackoverflow.com/a/64083631/2329968
def linspace(start, stop, step=1.):
"""
Like np.linspace but uses step instead of num
This is inclusive to stop, so if start=1, stop=3, step=0.5
Output is: array([1., 1.5, 2., 2.5, 3.])
"""
return np.linspace(start, stop, int((stop - start) / step 1))
t0 = 0
tf = 1 # arbitrary value
# discretize the time with a given deltat
time = linspace(t0, tf, deltat)
# compute x-y locations
x = ux0*time 0.5*ax*time**2
y = uy0*time 0.5*ay*time**2
# now there is a change that y < 0 for some x.
# We need to only keep the locations and times where y >= 0.
idx = y >= 0
x = x[idx]
y = y[idx]
time = time[idx]
# compute velocities
U = ux0 ax*time
V = uy0 ay*time
def buildframes(i):
line.set_data(x[:i 1], y[:i 1])
points.set_offsets([x[i], y[i]])
index.set_text('time = %.3f s' % time[i])
## Plotting
fig = plt.figure()
axes = fig.add_subplot(1,1,1)
line, = axes.plot([], [], zorder=1) # , 'bo', lw=2, scalex = True, scaley = True
points = plt.scatter([], [], c='red', s=15, zorder=2)
axes.set_ylim(min(y), np.true_divide(np.ceil(max(y) * 10**2), 10**2))
axes.set_xlim(min(x), np.true_divide(np.ceil(max(x) * 10**2), 10**2))
plt.ylabel('Height')
plt.xlabel('Distance')
index = axes.annotate('', xy=(0.75, 0.95), xycoords='axes fraction')
animator = ani.FuncAnimation(fig, buildframes, frames=len(x), interval=500)
# plt.show()
animator.save('animation.gif')
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/483601.html
標籤:Python 麻木的 matplotlib 动画 gif
上一篇:影片線性漸變
下一篇:意外的CSS反轉影片
