pythonmatplotlibcolorbar

Colormap of imshow not linked to surface_plot


I have created a figure with two subplots. On the left is a 3D surface plot and on the right side is 2D projection of the 3D plot with imshow. I want the colormap of the imshow plot to be linked to the 3D plot. But the scale does not fit.

import numpy as np
import matplotlib.pyplot as plt

id = np.arange(-600,750,150)
iq = np.arange(-600,750,150)

xx,yy = np.meshgrid(id,iq)

T = np.array([[-8988, -8697.5, -7847, -6923, -5610.5, -4536, -3374.35, -2572.85, -1987.65],
              [-8162, -7910, -7206.5, -6160, -4798.5, -3476.55, -2479.4, -1711.5, -1374.45],
              [-6513.5, -6814.5, -6398, -5218.5, -3706.5, -2362.15, -1414.7, -1013.6,-883.05],
              [-4224.5,-4669,   -4686.5, -3755.5, -2217.6, -1079.4, -591.85, -313.005,-211.925],
              [0, 0,    0,  0,  0,  0,  0,  0,  0],
              [4420.5, 4833.5, 4749.5, 3787, 2221.1, 1054.55, 567.35, 280.42, 146.51],
              [6793.5, 7017.5, 6510, 5260.5, 3692.5, 2295.3, 1360.45, 914.55, 806.4],
              [8421, 8008, 7287, 6160, 4725, 3400.25, 2318.4, 1628.2, 1285.55],
              [9170, 8750, 7864.5, 6874, 5498.5, 4413.5, 3206.7, 2351.3, 1865.5]])


m = plt.cm.ScalarMappable()
m.set_array(T)
m.set_clim(-9000, 9000) # optional
fig = plt.figure(1, figsize=(12,6))
ax = fig.add_subplot(121, projection='3d')
ax.set_xlabel(r'$I_d$', fontsize=15)
ax.set_ylabel(r'$I_q$', fontsize=15)
ax.set_zlabel(r'$T$', fontsize=15)


ax.plot_surface(xx, yy, T, cmap=m.cmap, norm = m.norm)
ax2 = fig.add_subplot(122)
ax2.imshow(T, cmap=m.cmap, norm=m.norm,
           extent=(np.min(xx), np.max(xx), np.min(yy), np.max(yy)),
           interpolation=None)

cbar = fig.colorbar(
    plt.cm.ScalarMappable(),
    ax=ax2
)
plt.tight_layout()
plt.show()

Combined 3D/2D plot with colormap

I added a mappable to the plot but unfortunately the colormap is not linked to values of the z axis of the surface plot. The scale only shows values between 0 and 1. How can I connect the values of the T Matix to the colormap ?


Solution

  • There are two things here:

    1. The default origin for imshow (on your 2D plot) is "upper", meaning the vertical axis points downwards by default. Since you have the lower numbers at the bottom of your axis, you want to set origin="lower".

    2. You can use the mappable object that is created by imshow to create the colorbar, which will then make the colorbar limits match the data. Below I give the mappable returned by ax2.imshow the name im, which you can then use in fig.colorbar.

    im = ax2.imshow(T, cmap=m.cmap, norm=m.norm, 
                    origin='lower',
                    extent=(np.min(xx), np.max(xx), np.min(yy), np.max(yy)),
                    interpolation=None)
    
    cbar = fig.colorbar(im, ax=ax2)
    

    enter image description here