以下是我已经工作了几周的模型,随着我学习如何编码(编码新手),慢慢增加了更多的复杂性。如果不清楚,我正在尝试创建一个2种不同密度的颗粒模型,这些颗粒根据斯托克斯沉降速度(作为浓度的函数)来稳定。我无法让动画与第二个粒子一起工作(底部有一个动画粒子的工作代码)。我试图调试代码时打破了两个不同粒子的变量,但是没有运气确定我做错了什么。
非常感谢任何帮助!
import numpy as np
import matplotlib.pyplot as plt
from pylab import *
from matplotlib.animation import FuncAnimation
import random
import pdb
from scipy import spatial
from scipy.spatial import KDTree
n = 100
n2 = 50
sigma = 0.01
sigma2 = 0.01
pp = 2.56 # pp = particle density (Sphene=3.53) #(Feldspar=2.56)
#(g/cm^3)
pp2 = 3.53
pf = 2.7 # pf = fluid density(g/cm^3)
pf2 = 2.7
g = 9.8 # g = gravity (m/s^2)
g2 = 9.8
r = 0.003 # r = radius of sphere (meter)
r2 = 0.0002
mu = 0.53 # mu = dynamic viscosity of fluid (log10Poise)
mu2 = 0.53
rp = 0.01 #radius around particle to check for nearest neighbor
rp2 = 0.001
dt = 0.008
dt2 = 0.008
fig, ax = plt.subplots()
az = plt.axes(xlim=(-.5, .5), ylim=(-1, 0))
xdata, ydata = [0.0], [0.0]
xdata2, ydata2 = [0.0], [0.0]
ln, = plt.plot([], [], marker= 'o',
markerfacecolor='r',markeredgecolor='k', linestyle='None',
animated=True)
ln2, = plt.plot([], [], marker= 's',
markerfacecolor='b',markeredgecolor='k', linestyle='None',
animated=True)
#pdb.set_trace()
def v_stokes(pp,pf,g,r,mu):
top=2*(pp-pf)*g*(r**2)
bottom=9*mu
ws=top/bottom
return ws
def v_stokes2(pp2,pf2,g2,r2,mu2):
top2=2*(pp2-pf2)*g2*(r2**2)
bottom2=9*mu2
ws2=top2/bottom2
return ws2
def init():
ax.set_xlim( -2, 2)
ax.set_ylim(-10, 0)
return ln, ln2,
def concentration(xdata, ydata, rp):
coords = list(zip(xdata, ydata))
tree = spatial.KDTree(coords)
test = np.column_stack([xdata, ydata])
nnl = tree.query_ball_point(test, rp) #nearest neighbors as a list
#(had tree in here before test but shape was wrong)
#pdb.set.trace()
nnt = np.zeros(len(nnl)) #nearest neighbors total
for i in range(len(nnt)):
nnt[i] = len(nnl[i])
return nnt
def concentration2(xdata2, ydata2, rp2):
coords2 = list(zip(xdata2, ydata2))
tree2 = spatial.KDTree(coords2)
test2 = np.column_stack([xdata2, ydata2])
nnl2 = tree2.query_ball_point(test2, rp2)
nnt2 = np.zeros(len(nnl2)) #nearest neighbors total
for i in range(len(nnt2)):
nnt2[i] = len(nnl2[i])
return nnt2
#y0 = []
#y1 = []
#y2 = []
#y3 = []
#y4 = []
def update(frame):
global xdata
global ydata
global concentration, v_stokes, pp, pf, g, r, mu, rp, dt, n, sigma
xdata = xdata + np.random.normal(0, sigma, n)
wss = v_stokes(pp,pf,g,r,mu)
if frame == 0.0:
ydata = np.zeros(len(xdata)) #makes the ydata length = xdata at
#time 0 print(ydata)
rp = 0.003
if frame > 10:
rp = 0.008
cp = concentration(xdata, ydata, rp)
if np.any(cp == 1):
cp = cp-1
if frame > 0.0:
#y0.append(ydata)
#y1.append(wss)
#y2.append(cp)
#y3.append(dt)
#y4.append(xdata)
ydata = ydata + (wss*(1-cp)**3) - dt # [0]
for v in ydata:
if v < -1.001:
ydata = -1
ln.set_data(xdata, ydata)
return ln,
def update2(frame2):
global xdata2
global ydata2
global concentration2, v_stokes2, pp2, pf2, g2, r2, mu2, rp2, dt2,
n2, sigma2
xdata2 = xdata2 + np.random.normal(0, sigma2, n2)
wss2 = v_stokes2(pp2,pf2,g2,r2,mu2)
if frame2 == 0.0:
ydata2 = np.zeros(len(xdata2)) #makes the ydata length = xdata
#at time 0 print(ydata)
rp2 = 0.003
if frame2 > 10:
rp2 = 0.008
cp2 = concentration2(xdata2, ydata2, rp2)
if np.any(cp2 == 1):
cp2 = cp2-1
if frame2 > 0.0:
#y5.append(ydata2)
#y6.append(wss2)
#y7.append(cp2)
#y8.append(dt2)
#y9.append(xdata2)
ydata2 = ydata2 + (wss2*(1-cp2)**3) - dt2 # [0]
for v2 in ydata2:
if v2 < -1.001:
ydata2 = -1
ln2.set_data(xdata2, ydata2)
return ln2,
def update_all(i):
l1 = update(i)
l2 = update2(i)
return l1, l2,
ani = FuncAnimation(fig, update_all, frames=range(0,200),
init_func=init, blit=True, interval=100, repeat =
False)
# change frames=range(0:1000) to change the number of frames
plt.show()
以下是包含一个动画粒子的原始工作代码:
import numpy as np
import matplotlib.pyplot as plt
from pylab import *
from matplotlib.animation import FuncAnimation
import random
import pdb
from scipy import spatial
from scipy.spatial import KDTree
n=100
sigma= 0.01
#m = np.random.uniform(n)
pp = 2.56 # pp = particle density (Sphene=3.53) #(Feldspar=2.56)
#(g/cm^3)
pf = 2.7 # pf = fluid density(g/cm^3)
g = 9.8 # g = gravity (m/s^2)
r = 0.003 # r = radius of sphere (meter)
mu = 0.53 # mu = dynamic viscosity of fluid (log10Poise)
rp = 0.01 #radius around particle to check for nearest neighbor
dt =0.008
fig, ax = plt.subplots()
az = plt.axes(xlim=(-.5, .5), ylim=(-1, 0))
xdata, ydata = [0.0], [0.0]
ln, = plt.plot([], [], marker= 'o',
markerfacecolor='r',markeredgecolor='k', linestyle='None',
animated=True)
#pdb.set_trace()
def v_stokes(pp,pf,g,r,mu):
top=2*(pp-pf)*g*(r**2)
bottom=9*mu
ws=top/bottom
return ws
def init():
ax.set_xlim( -2, 2)
ax.set_ylim(-10, 0)
return ln,
def concentration(xdata, ydata, rp):
coords = list(zip(xdata, ydata))
tree = spatial.KDTree(coords)
test = np.column_stack([xdata, ydata])
nnl = tree.query_ball_point(test, rp) #nearest neighbors as a list
#(had tree in here before test but shape was wrong)
#pdb.set.trace()
nnt = np.zeros(len(nnl)) #nearest neighbors total
for i in range(len(nnt)):
nnt[i] = len(nnl[i])
return nnt
y0 = []
y1 = []
y2 = []
y3 = []
y4 = []
def update(frame):
global xdata
global ydata
global concentration, v_stokes, pp, pf, g, r, mu, rp, dt, n
xdata = xdata + np.random.normal(0, sigma, n)
wss = v_stokes(pp,pf,g,r,mu)
#print(wss)
if frame == 0.0:
ydata = np.zeros(len(xdata)) #makes the ydata length = xdata at
#time 0 print(ydata)
rp = 0.003
if frame > 10:
rp = 0.008
if frame > 30:
rp = 0.01
if frame > 50: #notice that the particles move up instead of just
#slowing down
rp = 0.013
cp = concentration(xdata, ydata, rp)
#print(cp)
if np.any(cp == 1):
cp = cp-1
#print(xdata)
print(cp)
if frame > 0.0:
y0.append(ydata)
y1.append(wss)
y2.append(cp)
y3.append(dt)
y4.append(xdata)
ydata = ydata + (wss*(1-cp)**3) - dt # [0]
for v in ydata:
if v < -1.001:
ydata = -1
#if np.all(ydata) > 0:
#print(ydata)
#print(frame)
#print(ydata[0:5])
#ydata = ydata + (wss*(1-cp))
ln.set_data(xdata, ydata)
return ln,
#print(test)
ani = FuncAnimation(fig, update, frames=range(0,200),
init_func=init, blit=True, interval=100, repeat =
False)
# change frames=range(0:1000) to change the number of frames
plt.show()
答案 0 :(得分:0)
matplotlib.animation.FuncAnimation(fig, func, ...)
期望第二个参数是可调用的(例如函数)来更新图。
func
:可调用的 每帧调用的函数。第一个参数将是帧中的下一个值。可以通过fargs参数提供任何其他位置参数。
如果您有两个要更新的功能,则需要将它们合并为一个,
def update_all(i):
l1 = update(i)
l2 = update2(i)
return l1,l2
ani = FuncAnimation(fig, update_all, frames=range(0,200), init_func=init, ...)
请注意,您需要以与通常相同的方式定义plot
ln, = plt.plot
,并且需要在两个更新函数中返回行对象本身。
完整的运行代码:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from scipy import spatial
n=100
sigma= 0.01
pp = 2.56 # pp = particle density (Sphene=3.53) #(Feldspar=2.56)
#(g/cm^3)
pp2 = 3.53
pf = 2.7 # pf = fluid density(g/cm^3)
pf2 = 2.7
g = 9.8 # g = gravity (m/s^2)
g2 = 9.8
r = 0.003 # r = radius of sphere (meter)
r2 = 0.0002
mu = 0.53 # mu = dynamic viscosity of fluid (log10Poise)
mu2 = 0.53
rp = 0.01 #radius around particle to check for nearest neighbor
rp2 = 0.001
dt = 0.008
dt2 = 0.008
fig, ax = plt.subplots()
az = plt.axes(xlim=(-.5, .5), ylim=(-1, 0))
xdata, ydata = [0.0], [0.0]
xdata2, ydata2 = [0.0], [0.0]
ln, = plt.plot([], [], marker= 'o',
markerfacecolor='r',markeredgecolor='k', linestyle='None',
animated=True)
ln2, = plt.plot([], [], marker= 's',
markerfacecolor='b',markeredgecolor='k', linestyle='None',
animated=True)
#pdb.set_trace()
def v_stokes(pp,pf,g,r,mu):
top=2*(pp-pf)*g*(r**2)
bottom=9*mu
ws=top/bottom
return ws
def v_stokes2(pp2,pf2,g2,r2,mu2):
top2=2*(pp2-pf2)*g2*(r2**2)
bottom2=9*mu2
ws2=top2/bottom2
return ws2
def init():
ax.set_xlim( -2, 2)
ax.set_ylim(-10, 0)
return ln, ln2
def concentration(xdata, ydata, rp):
coords = list(zip(xdata, ydata))
tree = spatial.KDTree(coords)
test = np.column_stack([xdata, ydata])
nnl = tree.query_ball_point(test, rp)
nnt = np.zeros(len(nnl)) #nearest neighbors total
for i in range(len(nnt)):
nnt[i] = len(nnl[i])
return nnt
def concentration2(xdata2, ydata2, rp2):
coords2 = list(zip(xdata2, ydata2))
tree2 = spatial.KDTree(coords2)
test2 = np.column_stack([xdata2, ydata2])
nnl2 = tree2.query_ball_point(test2, rp2)
nnt2 = np.zeros(len(nnl2)) #nearest neighbors total
for i in range(len(nnt2)):
nnt2[i] = len(nnl2[i])
return nnt2
y0 = [];y1 = [];y2 = [];y3 = [];y4 = []
def update(frame):
global xdata
global ydata
global concentration, v_stokes, pp, pf, g, r, mu, rp, dt, n
xdata = xdata + np.random.normal(0, sigma, n)
wss = v_stokes(pp,pf,g,r,mu)
if frame == 0.0:
ydata = np.zeros(len(xdata)) #makes the ydata length = xdata at
#time 0 print(ydata)
rp = 0.003
if frame > 10:
rp = 0.008
if frame > 30:
rp = 0.01
if frame > 50: #notice that the particles move up instead of just
#slowing down
rp = 0.013
cp = concentration(xdata, ydata, rp)
if np.any(cp == 1):
cp = cp-1
#print(cp)
if frame > 0.0:
y0.append(ydata)
y1.append(wss)
y2.append(cp)
y3.append(dt)
y4.append(xdata)
ydata = ydata + (wss*(1-cp)**3) - dt # [0]
for j,v in enumerate(ydata):
if v < -1.001:
ydata[j] = -1
ln.set_data(xdata, ydata)
return ln
def update2(frame2):
global xdata2
global ydata2
global concentration2, v_stokes, pp2, pf2, g2, r2, mu2, rp2, dt2, n
xdata2 = xdata2 + np.random.normal(0, sigma, n)
wss2 = v_stokes2(pp2,pf2,g2,r2,mu2)
if frame2 == 0.0:
ydata2 = np.zeros(len(xdata2)) #makes the ydata length = xdata
#at time 0 print(ydata)
rp2 = 0.003
if frame2 > 10:
rp2 = 0.008
if frame2 > 30:
rp2 = 0.01
if frame2 > 50: #notice that the particles move up instead of just
#slowing down
rp2 = 0.013
cp2 = concentration2(xdata2, ydata2, rp2)
if np.any(cp2 == 1):
cp2 = cp2-1
if frame2 > 0.0:
y0.append(ydata2)
y1.append(wss2)
y2.append(cp2)
y3.append(dt2)
y4.append(xdata2)
ydata2 = ydata2 + (wss2*(1-cp2)**3) - dt2 # [0]
for j,v in enumerate(ydata2):
if v < -1.001:
ydata2[j] = -1
ln2.set_data(xdata2, ydata2)
return ln2
def update_all(i):
l1 = update(i)
l2 = update2(i)
return l1,l2
ani = FuncAnimation(fig, update_all, frames=range(0,200),
init_func=init, blit=True, interval=100, repeat = False)
plt.show()
&#13;
由于代码对于两个粒子类来说似乎多余,我建议通过将它放入类中来简化它。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from scipy import spatial
n=100
sigma= 0.01
pp = 2.56 # pp = particle density (Sphene=3.53) #(Feldspar=2.56)
#(g/cm^3)
pp2 = 3.53
pf = 2.7 # pf = fluid density(g/cm^3)
pf2 = 2.7
g = 9.8 # g = gravity (m/s^2)
g2 = 9.8
r = 0.003 # r = radius of sphere (meter)
r2 = 0.0002
mu = 0.53 # mu = dynamic viscosity of fluid (log10Poise)
mu2 = 0.53
rp = 0.01 #radius around particle to check for nearest neighbor
rp2 = 0.001
dt = 0.008
dt2 = 0.008
class Particles():
def __init__(self,ax, xdata,
pp, pf, g, r, mu, rp, dt, n,
marker="o",mfc="r"):
self.xdata=xdata
self.ydata = np.zeros(len(self.xdata))
self.pp=pp;self.pf=pf;self.g=g;self.r=r;self.mu=mu
self.rp=rp;self.dt=dt;self.n=n
self.ln, = ax.plot([], [], marker= marker,
markerfacecolor=mfc,markeredgecolor='k', linestyle='None',
animated=True)
def v_stokes(self, pp,pf,g,r,mu):
top=2*(pp-pf)*g*(r**2)
bottom=9*mu
return top/bottom
def concentration(self,xdata, ydata, rp):
coords = list(zip(xdata, ydata))
tree = spatial.KDTree(coords)
test = np.column_stack([xdata, ydata])
nnl = tree.query_ball_point(test, rp)
nnt = np.zeros(len(nnl)) #nearest neighbors total
for i in range(len(nnt)):
nnt[i] = len(nnl[i])
return nnt
def update(self, frame):
self.xdata += np.random.normal(0, sigma, n)
if frame == 0:
self.ydata = np.zeros(len(self.xdata))
wss = self.v_stokes(self.pp,self.pf,self.g,self.r,self.mu)
cp = self.concentration(self.xdata, self.ydata, self.rp)
if np.any(cp == 1):
cp = cp-1
if frame > 0.0:
self.ydata += (wss*(1-cp)**3) - dt
for j,v in enumerate(self.ydata):
if v < -1.001:
self.ydata[j] = -1
self.ln.set_data(self.xdata, self.ydata)
return self.ln
fig, ax = plt.subplots()
xdata, xdata2 = [0.0], [0.0]
p1 = Particles(ax,xdata, pp, pf, g, r, mu, rp, dt, n,
marker="o",mfc="r")
p2 = Particles(ax,xdata2, pp2, pf2, g2, r2, mu2, rp2, dt2, n,
marker="s",mfc="b")
def init():
ax.set_xlim(-2, 2)
ax.set_ylim(-1, 1)
return p1.ln, p2.ln
def update(i):
l1 = p1.update(i)
l2 = p2.update(i)
return l1, l2
ani = FuncAnimation(fig, update, frames=range(0,200),
init_func=init, blit=True, interval=100, repeat = False)
plt.show()
&#13;