pythonmatplotlib

Mismatch between the volume shape and the axes grid in matplotlib


I have written a script to visualize a 3D volume using Matplotlib. The decay volume is explicitly centered at x = y = 0, but the grid displayed appears displaced relative to the volume. This seems to be an issue with the grid, not the decay volume definition.

The script is provided below, and I also attach the result of its execution.

Could you please tell me what might be causing the grid to be misaligned, and how can I fix it? I believe the issue is with how the grid limits or alignment are set.

The script:

# funcs/setup.py

from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import matplotlib.pyplot as plt

z_min = 32
z_max = 82  
Delta_x_in = 1 
Delta_x_out = 4
Delta_y_in = 2.7
Delta_y_out = 6.2 

def x_max(z):
    return (Delta_x_in/2 * (z - z_max) / (z_min - z_max) +
            Delta_x_out/2 * (z - z_min) / (z_max - z_min))

def y_max(z):
    return (Delta_y_in/2 * (z - z_max) / (z_min - z_max) +
            Delta_y_out/2 * (z - z_min) / (z_max - z_min))

def plot_decay_volume(ax):
    x_min_zmin = -x_max(z_min)
    x_max_zmin_val = x_max(z_min)
    y_min_zmin = -y_max(z_min)
    y_max_zmin_val = y_max(z_min)

    x_min_zmax = -x_max(z_max)
    x_max_zmax_val = x_max(z_max)
    y_min_zmax = -y_max(z_max)
    y_max_zmax_val = y_max(z_max)

    vertices = [
        [x_min_zmin, y_min_zmin, z_min],         
        [x_max_zmin_val, y_min_zmin, z_min],     
        [x_max_zmin_val, y_max_zmin_val, z_min], 
        [x_min_zmin, y_max_zmin_val, z_min],     
        [x_min_zmax, y_min_zmax, z_max],         
        [x_max_zmax_val, y_min_zmax, z_max],     
        [x_max_zmax_val, y_max_zmax_val, z_max], 
        [x_min_zmax, y_max_zmax_val, z_max]      
    ]

    edges = [
        [vertices[0], vertices[1]],
        [vertices[1], vertices[2]],
        [vertices[2], vertices[3]],
        [vertices[3], vertices[0]],
        [vertices[4], vertices[5]],
        [vertices[5], vertices[6]],
        [vertices[6], vertices[7]],
        [vertices[7], vertices[4]],
        [vertices[0], vertices[4]],
        [vertices[1], vertices[5]],
        [vertices[2], vertices[6]],
        [vertices[3], vertices[7]]
    ]

    for edge in edges:
        xs, ys, zs = zip(*edge)
        ax.plot(xs, ys, zs, color='gray', linewidth=1)

    faces = [
        [vertices[0], vertices[1], vertices[2], vertices[3]],
        [vertices[4], vertices[5], vertices[6], vertices[7]],
        [vertices[0], vertices[1], vertices[5], vertices[4]],
        [vertices[1], vertices[2], vertices[6], vertices[5]],
        [vertices[2], vertices[3], vertices[7], vertices[6]],
        [vertices[3], vertices[0], vertices[4], vertices[7]]
    ]

    face_collection = Poly3DCollection(faces, linewidths=0.5, edgecolors='gray', alpha=0.3)
    face_collection.set_facecolor('lightgray')
    ax.add_collection3d(face_collection)

def visualize_decay_volume():
    fig = plt.figure(figsize=(10, 8))
    ax = fig.add_subplot(111, projection='3d')
    plot_decay_volume(ax)
    ax.set_xlabel('X (m)')
    ax.set_ylabel('Y (m)')
    ax.set_zlabel('Z (m)')
    x_lim = max(abs(x_max(z_min)), abs(x_max(z_max))) + 1
    y_lim = max(abs(y_max(z_min)), abs(y_max(z_max))) + 1
    ax.set_xlim(-x_lim, x_lim)
    ax.set_ylim(-y_lim, y_lim)
    ax.set_zlim(z_min - 5, z_max + 5)
    ax.set_title('Decay Volume')
    plt.show()

if __name__ == "__main__":
    visualize_decay_volume()

The output:

I have removed the axes scaling, but got a similar problem:


Solution

  • This is simply a result of your choice of z-limits. You've chosen to adjust the limits so the volume is not on the bottom plane, so the perspective makes it look like the volume isn't centered. If you adjust ax.set_zlim(z_min - 5, z_max + 5) to be ax.set_zlim(z_min, z_max + 5) you will see that the volume appears centered.