Search code examples
pythonmatplotlibgraphgraphics3d

How can I colour my 3d graph, used fourth variable's value?


I want to build the graph of complex function and use Matplotlib for that. But it can visualize only value of three variable and i want colour my graph as light as much value of fourth variable. Matplotlib allows to do that only with third variable's value. My code (still without fourth variable):

import pylab as pl
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.colors import LinearSegmentedColormap
from matplotlib import cm
import numpy as np

def makeData ():
    x = np.arange (-10, 10, 0.1)
    y = np.arange (-10, 10, 0.1)
    xgrid, ygrid = np.meshgrid(x, y)
    zgrid = np.sin (xgrid) * np.sin (ygrid) / (xgrid * ygrid)
    return xgrid, ygrid, zgrid

x, y, z = makeData()

fig = pl.figure()
axes = Axes3D(fig, auto_add_to_figure=False)
fig.add_axes(axes)

axes.plot_surface(x, y, z, rstride=4, cstride=4, cmap = cm.jet)
pl.show()

Exactly this code uses value of z and colour graph:

axes.plot_surface(x, y, z, rstride=4, cstride=4, cmap = cm.jet)

Can you help me?


Solution

  • You're reusing a decade old piece of code,... Pylab, Axes3D are very out of fashion!

    I'll show you how you can implement your idea using modern Matplotlib.

    ax.plot_surface supports the facecolor=array keyword argument, where array is an array of RGBA colors with the same shape as X, Y and Z, that you can generate from the array of 4th values using a colormap and a norm.

    In [31]: import numpy as np
        ...: import matplotlib as mp
        ...: import matplotlib.pyplot as plt
        ...: 
        ...: fig, ax = plt.subplots(subplot_kw=dict(projection="3d"),
        ...:                        constrained_layout=1)
        ...: x = y = np.linspace(0, 1, 11)
        ...: X, Y = np.meshgrid(x, y)
        ...: Z = X+Y # elevations
        ...: V = X-Y # 4th value
        ...: 
        ...: norm = plt.Normalize(vmin=V.min().min(), vmax=V.max().max())
        ...: ax.plot_surface(X, Y, V, facecolors=plt.cm.plasma(norm(V)))
        ...: m = mp.cm.ScalarMappable(cmap=plt.cm.plasma, norm=norm)
        ...: plt.colorbar(m)
        ...: plt.show()
    

    enter image description here