pythonnumpymatplotlib

How do I remove overflow along the z-axis for a 3D matplotlib surface?


I'm trying to graph a 3d mesh surface with matplotlib and constrain the limits of the graph. The X and Y axes are correctly constrained, but there is overflow in the Z-Axis.

What am I missing? Here's my code:

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

fig = plt.figure(figsize=(10,10))

x = np.linspace(-6,6,100)
y = np.linspace(-6,6,100)
X,Y = np.meshgrid(x,y)

def f(x,y):
    return x**2 + 3*y

Z = f(X,Y)


ax = plt.axes(projection = '3d')
ax.plot_surface(X,Y,Z,cmap='viridis')

ax.title.set_text("z=x**2+3y")
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')

ax.set_zlim3d(zmin=-3,zmax=5)
ax.set_xlim3d(xmin=-6,xmax=6)
ax.set_ylim3d(ymin=-6,ymax=6)

plt.show()

The graph:

Overflowing graph

Edit:

When I add clipping/min/max to the Z values, the graph is a little better, but it sets z values outside the bounds to the bounds themselves. Both of the following suggestions do this. Perhaps it's because I'm on a mac?

z_tmp = np.maximum(np.minimum(5,Z),-3)
z_temp = np.clip(Z, -3, 5, None)

better graph


Solution

  • Your data is outside the axis boundaries. Try rotate the view and you will notice.

    z = x**2 + 3*y
    

    If you want to only show a defined area of the data you could add a max() min() limitation on the Z data to exclude the data outside your wanted limitations.

    Z = f(X,Y)
    
    z_tmp = np.maximum(np.minimum(5,Z),-3)
    
    
    ax = plt.axes(projection = '3d')
    ax.plot_surface(X,Y,z_tmp,cmap='viridis')
    

    I'm not sure the matplotlib behaves as it should in your default case.