LoginSignup
0
0

More than 1 year has passed since last update.

[Python] Matplotlibで3Dグラフのlimit axis

Last updated at Posted at 2020-06-16

Matplotlib で3Dグラフを作成するとき、グラフの軸のサイズを設定しつつ軸の比率を統一したいが plt.axes().set_aspect('equal') のような関数が 3D plot には存在しないので、その解決方法を。
(軌道のプロットなどで便利)

例えば、このプロットについて

# plot in 3D of candidate branches
fig = plt.figure(figsize=(12,10))
plt.rcParams["font.size"] = 20
ax = fig.gca(projection='3d')
# mass
ax.plot_wireframe(xperilune_m2, yperilune_m2, zperilune_m2, color="k", label='m2', alpha=0.1)
# LPO trajectory
ax.plot(dynmatLPO["x_arr"]*Lstar, dynmatLPO["y_arr"]*Lstar, dynmatLPO["z_arr"]*Lstar, c='m', linewidth='1.5', label='Halo')

軸のサイズを固めたいとする。$x$軸を$320000$から$470000$、$y$軸を$-60000$から$60000$、$z$軸を$-1000$から$1000$で止めたい場合、これらの中から最大のrangeをもつ範囲を max=range として計算し、これをもとにボックスを作成している。

def set_equal_axis(ax, xlims, ylims, zlims):
    """Helper function to set equal axis

    Args:
        ax (Axes3DSubplot): matplotlib 3D axis, created by `ax = fig.add_subplot(projection='3d')`
        xlims (np.array): array containing min and max value of x
        ylims (np.array): array containing min and max value of y
        zlims (np.array): array containing min and max value of z
    """
    # compute max required range
    max_range = np.array([xlims.max()-xlims.min(), ylims.max()-ylims.min(), zlims.max()-zlims.min()]).max() / 2.0
    # compute mid-point along each axis
    mid_x = (xlims.max() + xlims.min()) * 0.5
    mid_y = (ylims.max() + ylims.min()) * 0.5
    mid_z = (zlims.max() + zlims.min()) * 0.5
    # set limits to axis
    ax.set_xlim(mid_x - max_range, mid_x + max_range)
    ax.set_ylim(mid_y - max_range, mid_y + max_range)
    ax.set_zlim(mid_z - max_range, mid_z + max_range)
    return


# create plot
fig = plt.figure(figsize=(12,10))
plt.rcParams["font.size"] = 20
ax = fig.gca(projection='3d')

# mass
ax.plot_wireframe(xperilune_m2, yperilune_m2, zperilune_m2, color="k", label='m2', alpha=0.1)
# LPO trajectory
ax.plot(dynmatLPO["x_arr"]*Lstar, dynmatLPO["y_arr"]*Lstar, dynmatLPO["z_arr"]*Lstar, c='m', linewidth='1.5', label='Halo')

# set array for max/min boxing
xlims = np.array([320000, 470000])
ylims = np.array( [-60000, 60000])
zlims = np.array([-1000, 1000])
set_equal_axis(ax, xlims, ylims, zlims)

ax.grid()
plt.title(f'Targeting from {num_branch} manifolds')
ax.legend(loc='best')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
plt.show()

参考:
https://matplotlib.org/3.2.1/api/_as_gen/mpl_toolkits.mplot3d.axes3d.Axes3D.html
https://stackoverflow.com/questions/30196503/2d-plots-are-not-sitting-flush-against-3d-axis-walls-in-python-mplot3d/41779162#41779162

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0