Tim*_*sto 10 python matplotlib python-2.7 mplot3d
我正在尝试将2D数据绘制到3D轴上.我使用了3D形状,ax.plot_surface
但是我无法使2D数据与轴墙齐平ax.plot
.
这是一个精简的示例代码,显示了我对2D数据的问题:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Generate Example Data
x = [0.04,0,-0.04]
y = [0.04,0,-0.04]
z = [0.04,0,-0.04]
# Start plotting environment
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Plot 3 lines positioned against the axes "walls"
ax.plot(x,y,-0.08,zdir='z',c='r')
ax.plot(x,z, 0.08,zdir='y',c='g')
ax.plot(y,z,-0.08,zdir='x',c='b')
# Label each axis
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
# Set each axis limits
ax.set_xlim([-0.08,0.08])
ax.set_ylim([-0.08,0.08])
ax.set_zlim([-0.08,0.08])
# Equally stretch all axes
ax.set_aspect("equal")
# Set plot size for saving to disk
plt.gcf().set_size_inches(11.7,8.3)
# Save figure in .eps and .png format
plt.savefig('test.eps', format='eps')
plt.savefig('test.png', format='png', dpi=300)
# Display figure
plt.show()
Run Code Online (Sandbox Code Playgroud)
这给出了以下结果,您可以从中看到数据线的末端不位于轴线上(即,不与0.04和-0.04对齐):
通过交互式探索绘图,我确定将ax.plot
调用中的0.08更改为0.083(同时保持相关符号)允许绘图更适合墙壁.
我对此的解释是,该图不是强制我的轴限制,通过查看轴相遇的间距在图上看起来很明显,但是使用ax.get_xlim()
等,显示了我设置的值,因此我遗漏了一些东西.
关于如何让这些地块与墙壁齐平的任何想法?
非常感谢,
蒂姆
编辑:
我还尝试使用设置轴限制
ax.set_xlim3d(-0.08,0.08)
ax.set_ylim3d(-0.08,0.08)
ax.set_zlim3d(-0.08,0.08)
Run Code Online (Sandbox Code Playgroud)
和
ax.set_xlim3d([-0.08,0.08])
ax.set_ylim3d([-0.08,0.08])
ax.set_zlim3d([-0.08,0.08])
Run Code Online (Sandbox Code Playgroud)
没有运气.
我绝对倾向于将此归因于轴遇到的填充问题,但我无法找到任何有关此问题的文档.即.我将绘图位置设置为-0.08并将轴限制设置为-0.08,但绘图在末尾添加一点填充以使限制介于-0.082和-0.083之间.
我想要删除填充或获取填充值,以便我可以将其输入ax.plot
命令.
EDIT2:
遇到此问题但尚未解决问题的其他人 在mplot3d数字中更改网格墙的位置
你是对的,该mplot3d
模块包含一个函数,在它呈现轴之前,在轴的最小值和最大值之间添加填充.
不幸的是,填充量是硬编码的,并且在最新的matplotlib(v2.0)版本中目前不能用户更改.
解决方案1:修改源代码
我发现可以通过在axis3d.py源代码文件中注释掉两行源代码来禁用额外填充.(在matplotlib源目录中,这可以在mpl_toolkits> mplot3d> axis3d.py下找到)
在函数中_get_coord_info()
,函数首先使用getter函数get_w_lims()
来检索您设置的x,y和z限制.它不会直接修改它们,因此当您检查时ax.get_xlim()
,它仍会返回0.08和-0.08的值.
def _get_coord_info(self, renderer):
minx, maxx, miny, maxy, minz, maxz = self.axes.get_w_lims()
if minx > maxx:
minx, maxx = maxx, minx
if miny > maxy:
miny, maxy = maxy, miny
if minz > maxz:
minz, maxz = maxz, minz
mins = np.array((minx, miny, minz))
maxs = np.array((maxx, maxy, maxz))
centers = (maxs + mins) / 2.
deltas = (maxs - mins) / 12.
mins = mins - deltas / 4.
maxs = maxs + deltas / 4.
vals = mins[0], maxs[0], mins[1], maxs[1], mins[2], maxs[2]
tc = self.axes.tunit_cube(vals, renderer.M)
avgz = [tc[p1][2] + tc[p2][2] + tc[p3][2] + tc[p4][2] for \
p1, p2, p3, p4 in self._PLANES]
highs = np.array([avgz[2*i] < avgz[2*i+1] for i in range(3)])
return mins, maxs, centers, deltas, tc, highs
Run Code Online (Sandbox Code Playgroud)
请注意,它以某种随意的方式计算填充.所以填充是不是一个固定的数字,但是是依赖于你所设定的轴限值.
deltas = (maxs - mins) / 12.
mins = mins - deltas / 4.
maxs = maxs + deltas / 4.
Run Code Online (Sandbox Code Playgroud)
当draw()
调用该函数来渲染轴时,它会使用这些修改过的mins
并maxs
构造您看到的实际线,这就是为什么总是在轴的每一端获得填充的原因.
我的hacky解决方案是只注释掉这两行:
#mins = mins - deltas / 4.
#maxs = maxs + deltas / 4.
Run Code Online (Sandbox Code Playgroud)
为您提供线条与3D轴墙齐平的图形.
但请注意底角的轴标签是如何相互重叠的,y标签似乎是错误对齐的...我怀疑这就是硬编码填充是一个特征的原因.这可能可以调整与旋转属性y轴刻度标记标签
的set_yticklabels(...)
方法,直到它看上去适合您的需求.
解决方案2:在交互式绘图窗口中使用缩放
不需要修改源代码的另一种(类型)解决方案是在交互式窗口中绘制图形,然后稍微放大直到线条与墙壁齐平.它需要一些试验和错误,因为它是一种"旁观"方法.请注意,这通常会删除最高刻度标记,但它避免了上述解决方案中的重叠问题:
解决方案3:结合以上所有内容
因此,鉴于我们知道如何mplot3d
计算填充量,我们是否可以使用它来将轴限制设置为恰当的数量,以避免填充问题,而无需使用交互模式或修改源代码?
是的,有一点额外的功能:
def get_fixed_mins_maxs(mins, maxs):
deltas = (maxs - mins) / 12.
mins = mins + deltas / 4.
maxs = maxs - deltas / 4.
return [mins, maxs]
minmax = get_fixed_mins_maxs(-0.08, 0.08)
# gives us: [-0.07666666666666667, 0.07666666666666667]
# Set each axis limits with the minmax value from our function
ax.set_xlim(minmax)
ax.set_ylim(minmax)
ax.set_zlim(minmax)
Run Code Online (Sandbox Code Playgroud)
这给出了解决方案2中的相同数字,无需打开交互式绘图窗口并通过眼睛判断.
归档时间: |
|
查看次数: |
929 次 |
最近记录: |