Search code examples
matplotlibsubplotcolorbar

Unique colorbar at the right of multiple subplots


I'm trying to add a unique colorbar to a set of 2x2 subplots and I'd like it to be on the right side of the ensemble. I have been able to generate the colorbar as you can see in the last lines of the code, but the result is that it appears to the right of the last panel (see figure below). Can someone help me find a solution?

import os
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm
import pandas as pd
mark=['-o','-s','-o','-^','-s']
Axs=['ax1','ax2','ax3','ax4']
RadiLabel=['5','7','10','15']
Lambda=np.arange(10,20,1)
print(Lambda[:])

Num_Colors=int(len(Lambda))
print(Num_Colors)
cm = plt.get_cmap('viridis_r')
# viridis,plasma,inferno,magma,gist_rainbow,gnuplot,autumn,Blues

mpl.rcParams['xtick.direction'] = 'in'
mpl.rcParams['ytick.direction'] = 'in'
mpl.rcParams['xtick.major.size'] = 15
mpl.rcParams['xtick.minor.size'] = 5
mpl.rcParams['ytick.major.size'] = 15
mpl.rcParams['ytick.minor.size'] = 5
mpl.rcParams['font.family'] = 'Calibri'

fig = plt.figure(figsize=(12,9))
#fig.subplots_adjust(right=0.8)

ax=fig.add_subplot(111)
ax.set_title('Area', fontsize=20)
plt.axis([0.8,15.2, 0.,0.3])

File= 'SCAli.txt'
data=np.loadtxt(File)
dat=pd.read_fwf("SCAli.txt",header=None,names=["Area","R","L","H"])

k=0
#print(len(Axs))
for j in range(0,len(Axs)):
    k=k+1
    axes=Axs[j]=plt.subplot(2,2,k)
    Axs[j].set_prop_cycle(color=[cm(1.*ii/Num_Colors) for ii in range(Num_Colors)])
    Axs[j].annotate('R= '+RadiLabel[j]+' nm', xy=(0.07, 0.9), xycoords="axes fraction",fontsize=20)

    for i in Lambda:
        dat2=dat.loc[(dat['L'] == i) & (dat['R'] == Radi[j])]
        Axs[j].plot(dat2['H'],dat2['Area'],mark[0],markersize=10,markeredgecolor='black',lw=2)
        plt.xlabel("Height", fontsize=30)
        plt.ylabel("Area", fontsize=30)
        plt.xticks(fontsize=20, rotation=0)
        plt.yticks(fontsize=20, rotation=0)
        Axs[j].minorticks_off()

plt.tight_layout()

# Here we plot the colorbar
sm = plt.cm.ScalarMappable(cmap=cm, norm=plt.Normalize(vmin=1, vmax=2))
cbar=plt.colorbar(sm)
cbar.ax.tick_params(labelsize=20)
cbar.set_label('$\lambda$',size=20)

plt.show()
plt.close()

This is the figure I get

Link to the file SCAli.txt


Solution

  • I have found the answer to my question. After some trials and looking at similar examples, I realized that adding the following lines of code would be enough:

        plt.subplots_adjust(bottom=0., right=0.92, top=1.)
        cax = plt.axes([0.95, 0.3, 0.025, 0.4])
        sm = plt.cm.ScalarMappable(cmap=cm, norm=plt.Normalize(vmin=1, vmax=2))
        cbar=plt.colorbar(sm,cax)
    
    1. The 1st command adjusts the four subplots to the left by changing the right= 1. to right=0.92, leaving space for the color bar to be placed to the right of them.
    2. The 2nd command generates new figure axis to be filled with the color bar. The numbers correspond to a rectangular area with the following characteristics [left, bottom, width, height], so that the colorbar can be varied in width, placement and length.
    3. Then, the 4th command plots the colorbar using the colormap cm, mapping the colors to the ones used in the subpanels as st by the 3rd command, and using the axes cax.

    This results in the following plot: Solution