具有matplotlib的对称流图 [英] Symmetric streamplot with matplotlib
问题描述
我正在尝试使用matplotlib绘制围绕球体的磁场流线,并且确实能很好地工作.但是,生成的图像不是对称的,但它应该是(我认为).
I'm trying to plot the streamlines of a magnetic field around a sphere using matplotlib, and it does work quite nicely. However, the resulting image is not symmetric, but it should be (I think).
这是用于生成图像的代码.请原谅篇幅,但我认为这比仅仅发布一个无效的片段要好.另外,它不是很pythonic.那是因为我从Matlab进行了转换,这比我预期的要容易.
This is the code used to generate the image. Excuse the length, but I thought it would be better than just posting a non-working snippet. Also, it's not very pythonic; that's because I converted it from Matlab, which was easier than I expected.
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
def cart2spherical(x, y, z):
r = np.sqrt(x**2 + y**2 + z**2)
phi = np.arctan2(y, x)
theta = np.arccos(z/r)
if r == 0:
theta = 0
return (r, theta, phi)
def S(theta, phi):
S = np.array([[np.sin(theta)*np.cos(phi), np.cos(theta)*np.cos(phi), -np.sin(phi)],
[np.sin(theta)*np.sin(phi), np.cos(theta)*np.sin(phi), np.cos(phi)],
[np.cos(theta), -np.sin(theta), 0]])
return S
def computeB(r, theta, phi, a=1, muR=100, B0=1):
delta = (muR - 1)/(muR + 2)
if r > a:
Bspherical = B0*np.array([np.cos(theta) * (1 + 2*delta*a**3 / r**3),
np.sin(theta) * (delta*a**3 / r**3 - 1),
0])
B = np.dot(S(theta, phi), Bspherical)
else:
B = 3*B0*(muR / (muR + 2)) * np.array([0, 0, 1])
return B
Z, X = np.mgrid[-2.5:2.5:1000j, -2.5:2.5:1000j]
Bx = np.zeros(np.shape(X))
Bz = np.zeros(np.shape(X))
Babs = np.zeros(np.shape(X))
for i in range(len(X)):
for j in range(len(Z)):
r, theta, phi = cart2spherical(X[0, i], 0, Z[j, 0])
B = computeB(r, theta, phi)
Bx[i, j], Bz[i, j] = B[0], B[2]
Babs[i, j] = np.sqrt(B[0]**2 + B[1]**2 + B[2]**2)
fig=plt.figure()
ax=fig.add_subplot(111)
plt.streamplot(X, Z, Bx, Bz, color='k', linewidth=0.8*Babs, density=1.3,
minlength=0.9, arrowstyle='-')
ax.add_patch(Circle((0, 0), radius=1, facecolor='none', linewidth=2))
plt.axis('equal')
plt.axis('off')
fig.savefig('streamlines.pdf', transparent=True, bbox_inches='tight', pad_inches=0)
推荐答案
首先,出于好奇,为什么要绘制对称数据?为什么绘制一半的图不是很好?
First of all, for curiosity, why would you want to plot symmetric data? Why plotting half of isn't fine?
说,这是一个可能的黑客.您可以按照 Hooked 的建议使用掩码数组来绘制其中的一半:
Said that, this is a possible hack. You can use mask arrays as Hooked suggested to plot half of it:
mask = X>0
BX_OUT = Bx.copy()
BZ_OUT = Bz.copy()
BX_OUT[mask] = None
BZ_OUT[mask] = None
res = plt.streamplot(X, Z, BX_OUT, BZ_OUT, color='k',
arrowstyle='-',linewidth=1,density=2)
然后将流图的结果保存在res中,提取线并使用相反的X坐标进行绘制.
then you save in res the result from streamplot, extract the lines and plot them with the opposite X coordinate.
lines = res.lines.get_paths()
for l in lines:
plot(-l.vertices.T[0],l.vertices.T[1],'k')
我使用这个 hack 从 2D 图中提取流线和箭头,然后应用 3D 转换并使用 mplot3d 绘制它.图片在我的一个问题这里中.
I used this hack to extract streamlines and arrows from a 2D plot, then apply a 3D transformation and plot it with mplot3d. A picture is in one of my questions here.
这篇关于具有matplotlib的对称流图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!