Я пытаюсь создать 3D-анимацию Matplotlib с контурным «срезом», который перемещается в пространстве. Минимальный рабочий пример того, что я пытаюсь выполнить, представлен следующим кодом:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation
from matplotlib.colors import TwoSlopeNorm
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(0, 1)
def f(X, Y, Z):
return ((Y-0.5)**2 + (Z-0.5)**2)*np.cos(X)
x = 0
intv = 0.01
x_vals = np.array([x])
y_vals = np.arange(0, 1, intv)
z_vals = np.arange(0, 1, intv)
X, Y, Z = np.meshgrid(x_vals, y_vals, z_vals)
norm = TwoSlopeNorm(0, -3, 3)
ctr = [ax.contourf(f(X, Y, Z).squeeze(), Y.squeeze(), Z.squeeze(), zdir='x', offset=x, levels=30, cmap='bwr', norm=norm)]
def animate(x):
for elm in ctr[0].collections:
elm.remove()
X, Y, Z = np.meshgrid(np.array([x]), y_vals, z_vals)
ctr[0] = ax.contourf(f(X, Y, Z).squeeze(), Y.squeeze(), Z.squeeze(), zdir='x', offset=x, levels=30, cmap='bwr', norm=norm)
anim = FuncAnimation(fig, animate, frames=np.arange(0, 1, intv), interval=20, repeat_delay=1000)
plt.show(block=True)
Однако это очень медленно, и мне было интересно, можно ли его использовать для повышения производительности. Я попытался сделать что-то вроде ответа на этот вопрос: увеличить скорость перерисовки контурного графика в matplotlib, в результате получился следующий код:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation
from matplotlib.colors import TwoSlopeNorm
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(0, 1)
def f(X, Y, Z):
return ((Y-0.5)**2 + (Z-0.5)**2)*np.cos(X)
x = 0
intv = 0.01
x_vals = np.array([x])
y_vals = np.arange(0, 1, intv)
z_vals = np.arange(0, 1, intv)
X, Y, Z = np.meshgrid(x_vals, y_vals, z_vals)
norm = TwoSlopeNorm(0, -3, 3)
ctr = [ax.contourf(f(X, Y, Z).squeeze(), Y.squeeze(), Z.squeeze(), zdir='x', offset=x, levels=30, cmap='bwr', norm=norm)]
def animate(x):
for elm in ctr[0].collections:
elm.remove()
X, Y, Z = np.meshgrid(np.array([x]), y_vals, z_vals)
ctr[0] = ax.contourf(f(X, Y, Z).squeeze(), Y.squeeze(), Z.squeeze(), zdir='x', offset=x, levels=30, cmap='bwr', norm=norm)
return ctr[0].collections
anim = FuncAnimation(fig, animate, frames=np.arange(0, 1, intv), interval=20, repeat_delay=1000, blit=True)
plt.show(block=True)
... Однако, это не работает - я получаю атрибут). Есть ли обходные пути к этому? Я видел упоминание об использовании do_3d_projection () для преобразования 3D -сцены в 2D, а затем проникнуть в это (я полагаю, это, вероятно, то, что пытается сделать вышеупомянутый код), но это не кажется возможным, если функция не реализован. Спасибо за помощь!
Я пытаюсь создать 3D-анимацию Matplotlib с контурным «срезом», который перемещается в пространстве. Минимальный рабочий пример того, что я пытаюсь выполнить, представлен следующим кодом: [code]import matplotlib.pyplot as plt import numpy as np from matplotlib.animation import FuncAnimation from matplotlib.colors import TwoSlopeNorm
def animate(x): for elm in ctr[0].collections: elm.remove() X, Y, Z = np.meshgrid(np.array([x]), y_vals, z_vals) ctr[0] = ax.contourf(f(X, Y, Z).squeeze(), Y.squeeze(), Z.squeeze(), zdir='x', offset=x, levels=30, cmap='bwr', norm=norm)
plt.show(block=True) [/code] Однако это очень медленно, и мне было интересно, можно ли его использовать для повышения производительности. Я попытался сделать что-то вроде ответа на этот вопрос: увеличить скорость перерисовки контурного графика в matplotlib, в результате получился следующий код: [code]import matplotlib.pyplot as plt import numpy as np from matplotlib.animation import FuncAnimation from matplotlib.colors import TwoSlopeNorm
def animate(x): for elm in ctr[0].collections: elm.remove() X, Y, Z = np.meshgrid(np.array([x]), y_vals, z_vals) ctr[0] = ax.contourf(f(X, Y, Z).squeeze(), Y.squeeze(), Z.squeeze(), zdir='x', offset=x, levels=30, cmap='bwr', norm=norm) return ctr[0].collections
plt.show(block=True) [/code] ... Однако, это не работает - я получаю атрибут). Есть ли обходные пути к этому? Я видел упоминание об использовании do_3d_projection () для преобразования 3D -сцены в 2D, а затем проникнуть в это (я полагаю, это, вероятно, то, что пытается сделать вышеупомянутый код), но это не кажется возможным, если функция не реализован. Спасибо за помощь!