2012-04-26 52 views
26

我想从海底的一个500m乘40m部分的声纳数据中绘制海底的3D图像。我正在用Axes3D使用matplotlib/mplot3d,我希望能够更改轴的纵横比,以便x轴能够缩放。与生成的数据,而不是真实数据的示例脚本是:设置三维图的纵横比

import matplotlib.pyplot as plt 
from matplotlib import cm 
from mpl_toolkits.mplot3d import Axes3D 
import numpy as np 

# Create figure. 
fig = plt.figure() 
ax = fig.gca(projection = '3d') 

# Generate example data. 
R, Y = np.meshgrid(np.arange(0, 500, 0.5), np.arange(0, 40, 0.5)) 
z = 0.1 * np.abs(np.sin(R/40) * np.sin(Y/6)) 

# Plot the data. 
surf = ax.plot_surface(R, Y, z, cmap=cm.jet, linewidth=0) 
fig.colorbar(surf) 

# Set viewpoint. 
ax.azim = -160 
ax.elev = 30 

# Label axes. 
ax.set_xlabel('Along track (m)') 
ax.set_ylabel('Range (m)') 
ax.set_zlabel('Height (m)') 

# Save image. 
fig.savefig('data.png') 

而从这个脚本的输出图像:

matplotlib output image

现在我想改变它,这样1米的沿轨道(x)轴与(y)轴范围内的1米相同(或者根据所涉及的相对尺寸可能有不同的比例)。由于数据中的相对大小,我还想设置z轴的比例,再次不需要1:1,但是轴比当前的图小。

我试图建立和使用this branch of matplotlib,按照this message from the mailing list示例脚本,但加入了ax.pbaspect = [1.0, 1.0, 0.25]行给我的脚本(已卸载matplotlib的“标准”版本,以确保定制的版本使用)没有做生成的图像有任何差异。

编辑:因此,所需的输出将如下所示(用Inkscape粗略编辑)图像。在这种情况下,我没有在x/y轴上设置1:1的比例,因为这看起来很可笑,但我已经分散了,所以它不像原始输出那样是方形的。

savefig前

Desired output

回答

18

添加以下代码:

ax.auto_scale_xyz([0, 500], [0, 500], [0, 0.15]) 

enter image description here

如果你不想要方轴:

编辑站点包内get_proj功能\ mpl_toolkits \ mplot3d \ axes3d.py:

xmin, xmax = self.get_xlim3d()/self.pbaspect[0] 
ymin, ymax = self.get_ylim3d()/self.pbaspect[1] 
zmin, zmax = self.get_zlim3d()/self.pbaspect[2] 

然后添加一条线来设置pbaspect:

ax = fig.gca(projection = '3d') 
ax.pbaspect = [2.0, 0.6, 0.25] 

enter image description here

+0

嗯。这确实会使轴的缩放比例正确,但会导致大量浪费的空间。虽然我*可以*将其保存为SVG并手动编辑(就像我对所需图像所做的一样,我只是更新了这个问题),当我创建大量图像时,这会变得非常乏味,而且我不会确保它可以自动化... – Blair 2012-04-27 04:04:52

+1

您可以使用pbaspect修改来获取没有方形轴。我编辑了答案。 – HYRY 2012-04-27 04:36:08

+0

太棒了,谢谢! – Blair 2012-04-28 01:18:47

5

答案this question作品完美的我。而且您不需要设置任何比例,它会自动完成所有操作。

0

我不知道怎么解决了浪费空间的问题:

try: 
    self.localPbAspect=self.pbaspect 
    zoom_out = (self.localPbAspect[0]+self.localPbAspect[1]+self.localPbAspect[2]) 
except AttributeError: 
    self.localPbAspect=[1,1,1] 
    zoom_out = 0 
xmin, xmax = self.get_xlim3d()/self.localPbAspect[0] 
ymin, ymax = self.get_ylim3d()/self.localPbAspect[1] 
zmin, zmax = self.get_zlim3d()/self.localPbAspect[2] 

# transform to uniform world coordinates 0-1.0,0-1.0,0-1.0 
worldM = proj3d.world_transformation(xmin, xmax, 
             ymin, ymax, 
             zmin, zmax) 

# look into the middle of the new coordinates 
R = np.array([0.5*self.localPbAspect[0], 0.5*self.localPbAspect[1], 0.5*self.localPbAspect[2]]) 
xp = R[0] + np.cos(razim) * np.cos(relev) * (self.dist+zoom_out) 
yp = R[1] + np.sin(razim) * np.cos(relev) * (self.dist+zoom_out) 
zp = R[2] + np.sin(relev) * (self.dist+zoom_out) 
E = np.array((xp, yp, zp))