【问题标题】:Move 3D plot to avoid clipping by margins移动 3D 绘图以避免边缘裁剪
【发布时间】:2015-07-24 23:56:12
【问题描述】:

我试图弄清楚如何让下面的 3D matplotlib 图像在画布上绘制得更高,这样它就不会被剪裁。这是我用来创建情节的代码。我找不到附加包含 Z 标高的文本文件的方法(在下面的代码中引用),但它只是一个包含由 0 到 1 之间的值组成的表面的二维数组。

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

nrow=30
ncol=100

f = open(r'C:\temp\fracEvapCume_200.txt','r')
fracEvapTS = np.loadtxt(f)
f.close()

X, Y = np.meshgrid(ncol, nrow)
Y3d, X3d = np.mgrid[0:Y, 0:X]

fig = plt.figure()
ax = fig.gca(projection='3d')
ax.auto_scale_xyz([0, 100], [0, 30], [0, 0.2])
Y3d, X3d = np.mgrid[0:Y, 0:X]
Z = fracEvapTS

surf = ax.plot_surface(X3d, Y3d, Z, cmap='autumn', cstride=2, rstride=2)
ax.set_xlabel("X-Label")
ax.set_ylabel("Y-Label")
ax.set_zlabel("Z-Label")
ax.pbaspect = [1., .33, 0.25]
ax.dist  = 7
plt.tight_layout()
plt.savefig('clipped.png')

为了使ax.pbaspect=[1., .33, 0.25] 行正常工作,按照this post 中的建议对site-packages\mpl_toolkits\mplot3d\axes3d.py 中的get_proj 函数进行了更改。为了让图形画得更大,我在this post的基础上添加了ax.dist = 7。最后,基于this post,我希望plt.tight_layout() 会回滚边距并防止下面显示的红色/黄色表面被剪裁,但这也不起作用。我找不到将图像在画布上向上移动的命令,从而避免了图形顶部所有不必要的空白并防止红色/黄色表面被剪裁。有没有一行 Python 可以做到这一点?

在添加plt.tight_layout()这行之后,事情变得更糟了:

【问题讨论】:

    标签: python matplotlib mplot3d


    【解决方案1】:

    问题是你对 site-packages\mpl_toolkits\mplot3d\axes3d.py 的修改改变了投影矩阵,而没有改变视图的中心,一旦变换就弄乱了场景的位置在相机坐标中。

    因此,当视图被缩放(ax.dist)然后移动时,绘图有时会超出画布。

    您需要将以下行替换为 axes3d.py 中的get_proj 函数:

        # look into the middle of the new coordinates
        R = np.array([0.5, 0.5, 0.5])
    

    作者:

        # look into the middle of the new coordinates
        try:
            R = np.array(self.pbaspect)/2
        except AttributeError:
            R = np.array([0.5, 0.5, 0.5])
    

    这应该可行:

    PS : 用于制作数字的代码:

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.cm as cm
    from mpl_toolkits.mplot3d import Axes3D
    
    nrow=30
    ncol=100
    
    X, Y = np.meshgrid(ncol, nrow)
    Y3d, X3d = np.mgrid[0:Y, 0:X]
    Z = np.sin(Y3d/Y)*np.sin(X3d/X)
    
    fig = plt.figure()
    for i in range(4):
        ax = fig.add_subplot(2,2,i,projection='3d')
        ax.auto_scale_xyz([0, 100], [0, 30], [0, 0.2])
    
        surf = ax.plot_surface(X3d, Y3d, Z, cmap='autumn', cstride=2, rstride=2)
        ax.set_xlabel("X-Label")
        ax.set_ylabel("Y-Label")
        ax.set_zlabel("Z-Label")
        ax.pbaspect = [1., .33, 0.25]
        ax.dist  = 7
    

    【讨论】:

    • 编辑get_proj 成功了。你知道哪一行脚本会减少出现在 z 轴上的数字标签以减少混乱吗?例如,在您的绘图中,您每 0.1 标记一次 z,如果您只想每 0.25 标记一次和标记怎么办?
    • 您可以使用ax.set_zticks( np.arange(zmin,zmax,step)) 做到这一点,只需提供您想要的值作为参数(在您的示例中:(0,0.25,0.16)
    猜你喜欢
    • 1970-01-01
    • 2016-05-19
    • 2019-09-21
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多