The (optional) triangulation can be specified in one of two ways; either:

plot_trisurf(triangulation, ...)
The remaining arguments are:

plot_trisurf(..., Z)
where triangulation is a Triangulation object, or:

plot_trisurf(X, Y, ...)
plot_trisurf(X, Y, triangles, ...)
plot_trisurf(X, Y, triangles=triangles, ...)

Alternatively, however, there is .plot_trisurf() which uses 1D inputs. I've added an example in the middle of the code.


import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
from mpl_toolkits.mplot3d import Axes3D

## Matplotlib Sample Code using 2D arrays via meshgrid
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X ** 2 + Y ** 2)
Z = np.sin(R)
fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)
ax.set_zlim(-1.01, 1.01)

ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

fig.colorbar(surf, shrink=0.5, aspect=5)
plt.title('Original Code')
plt.show()

As suggested in this post, you can use griddata for the color as well. The complete example (here with interpolation from matplotlib.tri) would look like this:


import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.tri as tri
from matplotlib.colors import Normalize

x = [10.0, 14.0, 18.0, 14.0, 6.0, 6.0, 2.0, 18.0, 18.0, 6.0, 18.0, 14.0, 10.0, 10.0, 6.0, 6.0, 10.0, 14.0, 2.0, 18.0, 10.0, 14.0]
y = [1.8, 1.4, 1.2, 2.0, 2.0, 1.4, 2.0, 1.8, 2.0, 1.8, 1.6, 1.8, 2.0, 1.2, 1.6, 1.2, 1.6, 1.2, 1.8, 1.4, 1.4, 1.6]
z = [1.22, 2.14, 1.66, 0.7, 2.86, 5.89, 3.85, 0.45, 0.4, 4.28, 0.6, 0.92, 0.67, 3.52, 5.25, 4.94, 1.37, 3.76, 4.75, 0.95, 1.99, 1.41]
z1 = [29.0, 26.72, 26.71, 31.33, 29.46, 24.84, 32.54, 31.43, 33.84, 28.14, 29.84, 31.34, 30.51, 25.0, 25.73, 24.06, 27.09, 26.89, 29.85, 28.93, 26.58, 27.53]


# domains
x = np.array(x)
y = np.array(y)
z = np.array(z)
z1 = np.array(z1)

# Create grid values first.
ngridx = 100
ngridy = 100
xi = np.linspace(x.min(), x.max(), ngridx)
yi = np.linspace(y.min(), y.max(), ngridy)

# Perform linear interpolation of the data (x,y)
# on a grid defined by (xi,yi)
triang = tri.Triangulation(x, y)
interpolator_z = tri.LinearTriInterpolator(triang, z)
interpolator_z1 = tri.LinearTriInterpolator(triang, z1)
Xi, Yi = np.meshgrid(xi, yi)
zi = interpolator_z(Xi, Yi)
z1i = interpolator_z1(Xi, Yi)

X, Y, Z, Z1 = xi, yi, zi, z1i

fig = plt.gcf()
ax1 = fig.add_subplot(111, projection='3d')

minn, maxx = z1.min(), z1.max()
norm = Normalize()
surf = ax1.plot_surface(X,Y,Z, rstride=1, cstride=1, facecolors=cm.jet(norm(Z1)), vmin=minn, vmax=maxx, shade=False)

m = cm.ScalarMappable(cmap=cm.jet)
m.set_array(Z1)
col = plt.colorbar(m)
plt.show()

Let me talk you through this example taken from the docs


'''
======================
Triangular 3D surfaces
======================

Plot a 3D surface with a triangular mesh.
'''

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


n_radii = 8
n_angles = 36

# Make radii and angles spaces (radius r=0 omitted to eliminate duplication).
radii = np.linspace(0.125, 1.0, n_radii)
angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)

# Repeat all angles for each radius.
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)

# Convert polar (radii, angles) coords to cartesian (x, y) coords.
# (0, 0) is manually added at this stage,  so there will be no duplicate
# points in the (x, y) plane.
x = np.append(0, (radii*np.cos(angles)).flatten())
y = np.append(0, (radii*np.sin(angles)).flatten())

# Compute z to make the pringle surface.
z = np.sin(-x*y)

fig = plt.figure()
ax = fig.gca(projection='3d')

ax.plot_trisurf(x, y, z, linewidth=0.2, antialiased=True)

plt.show()

Given the scattered nature of your data set, I'd suggest tri_surf. Since you're saying "it is not quite what [you] need", your other option is to create a meshgrid, then interpolate your input points with scipy.interpolate.griddata.


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

X = [1,1,1,1,2,2,2,2,3,3,3,3]
Y = [1,4,5,6,1,4,5,6,1,4,5,6]
Z = [2,6,3,6,2,7,4,6,2,4,2,3]

plotx,ploty, = np.meshgrid(np.linspace(np.min(X),np.max(X),10),\
                           np.linspace(np.min(Y),np.max(Y),10))
plotz = interp.griddata((X,Y),Z,(plotx,ploty),method='linear')

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(plotx,ploty,plotz,cstride=1,rstride=1,cmap='viridis')  # or 'hot'

You can use plot_trisurf and assign a custom field to the underlying ScalarMappable through set_array method.


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

(n, m) = (250, 250)

# Meshing a unit sphere according to n, m 
theta = np.linspace(0, 2 * np.pi, num=n, endpoint=False)
phi = np.linspace(np.pi * (-0.5 + 1./(m+1)), np.pi*0.5, num=m, endpoint=False)
theta, phi = np.meshgrid(theta, phi)
theta, phi = theta.ravel(), phi.ravel()
theta = np.append(theta, [0.]) # Adding the north pole...
phi = np.append(phi, [np.pi*0.5])
mesh_x, mesh_y = ((np.pi*0.5 - phi)*np.cos(theta), (np.pi*0.5 - phi)*np.sin(theta))
triangles = mtri.Triangulation(mesh_x, mesh_y).triangles
x, y, z = np.cos(phi)*np.cos(theta), np.cos(phi)*np.sin(theta), np.sin(phi)

# Defining a custom color scalar field
vals = np.sin(6*phi) * np.sin(3*theta)
colors = np.mean(vals[triangles], axis=1)

# Plotting
fig = plt.figure()
ax = fig.gca(projection='3d')
cmap = plt.get_cmap('Blues')
triang = mtri.Triangulation(x, y, triangles)
collec = ax.plot_trisurf(triang, z, cmap=cmap, shade=False, linewidth=0.)
collec.set_array(colors)
collec.autoscale()
plt.show()

Here is a commented code that works:


import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
fig = plt.figure(figsize=(12, 12))

ax = Axes3D(fig) # ax = fig.add_subplot(111, projection='3d')
ax.set_title("Plot 3d",fontsize=14)
ax.set_xlabel('Voltage (V)', fontsize=12)
ax.set_ylabel('Pulse Delay(ms)', fontsize=12)
ax.set_zlabel('Pulse Width(ms)', fontsize=12)
ax.grid(True, linestyle='-', color='0.75')

# 'i15' and 'f15' are not known as numerical types.
# You can use only 'i8' (np.int64) and 'f16' (np.float128) or 'f8' (np.float64).
# 'f16' seems not to be recognized as a valid type for the scatter library.
# I think that 'f8' and 'i8' are quoit enough.
data = np.genfromtxt('./sample.txt', dtype=[('col1', 'f8'), ('col2', 'i8'), ('col3',   'i8'), ('col4', 'S15')])

# scatter does not take for the c option a list of colours such as ['g', 'g', 'r', ...].
# In this case, we will define data for each colour, not a color for each scatter point.
m = data["col4"]
data1 = data[m == "PASS"]
data2 = data[m != "PASS"]

for dat, color in [(data1, 'g'), (data2, 'r')]:
    # Don't forget that having empty data columns may raise exceptions ...
    try:
        x, y, z = dat['col1'], dat['col2'], dat['col3']
        ax.scatter(xs=x, ys=y, zs=z, s=50, c=color, marker='o', linewidths=0)
    except:
        pass

plt.show()

A different approach, based on re-gridding the data, that doesn't require that the original data is specified on a regular grid [deeply inspired by this example;-].


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

np.random.seed(19880808)

# compute the sombrero over a cloud of random points
npts = 10000
x, y = np.random.uniform(-5, 5, npts), np.random.uniform(-5, 5, npts)
z = np.cos(1.5*np.sqrt(x*x + y*y))/(1+0.33*(x*x+y*y))

# prepare the interpolator
triang = tri.Triangulation(x, y)
interpolator = tri.LinearTriInterpolator(triang, z)

# do the interpolation
xi = yi = np.linspace(-5, 5, 101)
Xi, Yi = np.meshgrid(xi, yi)
Zi = interpolator(Xi, Yi)

# plotting
fig = plt.figure()
ax = fig.gca(projection='3d')
norm = plt.Normalize(-1,1)
ax.plot_surface(Xi, Yi, Zi,
                cmap='inferno',
                norm=plt.Normalize(-1,1))
plt.show()

Recommend

Matplotlib The mplot3d Toolkit

Matplotlib Overview of mpl_toolkits.axes_grid1 AxesDivider

Matplotlib Overview of mpl_toolkits.axes_grid1 axes_grid1 RGBAxes

Matplotlib Overview of mpl_toolkits.axes_grid1 axes_grid1 InsetLocator

Matplotlib Overview of mpl_toolkits.axes_grid1 axes_grid1 ParasiteAxes Example 2. twin

Matplotlib Overview of mpl_toolkits.axes_grid1 axes_grid1 colorbar whose height (or width) in sync with the master axes scatter_hist.py with AxesDivider

Matplotlib Overview of mpl_toolkits.axes_grid1 axes_grid1 AxesDivider Class

Matplotlib Image tutorial Plotting numpy arrays as images Array Interpolation schemes

Matplotlib Image tutorial Plotting numpy arrays as images Examining a specific data range

Matplotlib Image tutorial Plotting numpy arrays as images Color scale reference

Matplotlib Image tutorial Plotting numpy arrays as images Applying pseudocolor schemes to image plots

Matplotlib Image tutorial Plotting numpy arrays as images

Matplotlib Image tutorial Importing image data into Numpy arrays

Matplotlib Image tutorial Startup commands

Matplotlib Pyplot tutorial Logarithmic and other nonlinear axes

Matplotlib Pyplot tutorial Working with text Annotating text

Matplotlib Pyplot tutorial Working with text Using mathematical expressions in text

Matplotlib Pyplot tutorial Working with text

Matplotlib Pyplot tutorial Working with multiple figures and axes

Matplotlib Pyplot tutorial Controlling line properties

Matplotlib Pyplot tutorial Plotting with categorical variables

Matplotlib Pyplot tutorial Plotting with keyword strings

Matplotlib Pyplot tutorial Intro to pyplot Formatting the style of your plot

Matplotlib Pyplot tutorial Intro to pyplot

Matplotlib Basic Usage Working with multiple Figures and Axes

Matplotlib Basic Usage Color mapped data

Matplotlib Basic Usage Axis scales and ticks Additional Axis objects

Matplotlib Basic Usage Axis scales and ticks Plotting dates and strings

Matplotlib Basic Usage Axis scales and ticks Tick locators and formatters

Matplotlib Basic Usage Axis scales and ticks Scales

Matplotlib Basic Usage Labelling plots Legends

Matplotlib Basic Usage Labelling plots Annotations

Matplotlib Basic Usage Labelling plots Using mathematical expressions in text

Matplotlib Basic Usage Labelling plots Axes labels and text

Matplotlib Basic Usage Styling Artists Linewidths, linestyles, and markersizes

Matplotlib Basic Usage Styling Artists Colors

Matplotlib Basic Usage Styling Artists

Matplotlib Basic Usage Coding styles Making a helper functions

Matplotlib Basic Usage Coding styles The object-oriented and the pyplot interfaces

Matplotlib Basic Usage Types of inputs to plotting functions

Matplotlib Basic Usage Parts of a Figure Figure

Matplotlib Basic Usage A simple example

Matplotlib Basic Usage

Matplotlib The Lifecycle of a Plot Saving our plot

Matplotlib The Lifecycle of a Plot Combining multiple visualizations

Matplotlib The Lifecycle of a Plot Customizing the plot

Matplotlib The Lifecycle of a Plot Controlling the style

Matplotlib The Lifecycle of a Plot Getting started

Matplotlib The Lifecycle of a Plot Our data

Customizing Matplotlib with style sheets and rcParams The matplotlibrc file The default matplotlibrc file

Customizing Matplotlib with style sheets and rcParams The matplotlibrc file

Customizing Matplotlib with style sheets and rcParams Using style sheets Temporary styling

Customizing Matplotlib with style sheets and rcParams Using style sheets Composing styles

Customizing Matplotlib with style sheets and rcParams Using style sheets Defining your own style

Customizing Matplotlib with style sheets and rcParams Using style sheets

Customizing Matplotlib with style sheets and rcParams Runtime rc settings Temporary rc settings

Customizing Matplotlib with style sheets and rcParams Runtime rc settings

Matplotlib origin and extent in imshow Explicit extent and axes limits

Matplotlib origin and extent in imshow Explicit extent