0

I want to draw a figure of two subplots with one single colorbar. However, those two subplots are in different ranges. I tried to use contourf to make it, but failed. The colorbar of contourf always displays in the range of the last subplots, but what I need is the colorbar which is in the range of both 2 subplots. I changed the contourf to pcolor without any other codes modified and finally made it. I got inspirations from the link: Set Colorbar Range in matplotlib Thus I am confused that what works and why. The codes are attached

fig, axes = plt.subplots(nrows=1, ncols=2)
j = 0
for ax in axes.flat:
    if j == 0:
        Z = sensi_n_M(X,Y,n)
        varName = 'vegetation coverage'
        label = 'dM/M'
    elif j == 1:
        Z = sensi_n_AS(X,Y,n)
        varName = 'average slope'
        label = r'{dtan\beta/tan\beta}'
    title1 = ax.set_title(r'$\frac{dn/n}{'+label+'}$'+'\n', fontsize=25)
    ylabel=ax.yaxis.set_label_text('average slope')
    ylabel.set_fontsize(15)
    xlabel=ax.xaxis.set_label_text('vegetation coverage')
    xlabel.set_fontsize(15)
    for tick in ax.xaxis.get_major_ticks():  
            tick.label1.set_fontsize(10)
    for tick in ax.yaxis.get_major_ticks():  
            tick.label1.set_fontsize(10)
    fill = ax.pcolor(X, Y, Z, #rstride=1, cstride=1, #clevs,
                     #edgecolors = 'r',
                   cmap=plt.cm.RdBu_r,vmin=-2.4,vmax=1.2)
    j = j+1
v = np.linspace(-2.4,1.2,13)
fig.subplots_adjust(left=0.2, wspace=0.8, top=0.8)
cax,kw = mpl.colorbar.make_axes([ax for ax in axes.flat])
cb = fig.colorbar(fill, cax=cax)
cb.set_ticklabels(v)
plt.show()

The figure below is about the pcolor

enter image description here

However, the figure below is about the contourf

enter image description here

and the codes for the contourf plot is:

fig, axes = plt.subplots(nrows=1, ncols=2)
j = 0
for ax in axes.flat:
    if j == 0:
        Z = sensi_n_M(X,Y,n)
        varName = 'vegetation coverage'
        label = 'dM/M'
    elif j == 1:
        Z = sensi_n_AS(X,Y,n)
        varName = 'average slope'
        label = r'{dtan\beta/tan\beta}'
    title1 = ax.set_title(r'$\frac{dn/n}{'+label+'}$'+'\n', fontsize=25)
    ylabel=ax.yaxis.set_label_text('average slope')
    ylabel.set_fontsize(15)
    xlabel=ax.xaxis.set_label_text('vegetation coverage')
    xlabel.set_fontsize(15)
    for tick in ax.xaxis.get_major_ticks():  
            tick.label1.set_fontsize(10)
    for tick in ax.yaxis.get_major_ticks():  
            tick.label1.set_fontsize(10)
    fill = ax.contourf(X, Y, Z, rstride=1, cstride=1, #clevs,
                     #edgecolors = 'r',
                   cmap=plt.cm.RdBu_r,vmin=-2.4,vmax=1.2)
    j = j+1
v = np.linspace(-2.4,1.2,13)
fig.subplots_adjust(left=0.2, wspace=0.8, top=0.8)
cax,kw = mpl.colorbar.make_axes([ax for ax in axes.flat])
cb = plt.colorbar(fill, cax=cax)
cb.set_ticklabels(v)
plt.show()
Xu Shan
  • 175
  • 3
  • 11

1 Answers1

1

If you are asking why one of them seems to be in patches and the other one seems to be more continuous, that is intentional and is depended on what kind of mappable you are typing to draw colorbar from.

See source code here, basically it checks if the mappable is a counterset, if so it will draw a ColorbarPatch, otherwise draw a normal Colorbar. A few lines above that you can see the ColorbarPatch class basically extends from the Colorbar class, and essentially draws the colorbar in a set of discrete levels by overriding the _add_solids methods (which are in turn matches the levels from the ContourSet you supplied as the mappable parameter).

CT Zhu
  • 52,648
  • 17
  • 120
  • 133
  • I am afraid not. I am confused about the range of the colorbar. The 'contourf' one is just from -2.4 to 0, but the 'pcolor' one is from -2.4 to 1.2. – Xu Shan Sep 09 '18 at 01:43
  • The axis limit is controlled the same way in `Colorbar` and `ColorbarPatch`. However effectively the former essential uses the range of the data, the latter uses the range of the discrete levels. I noticed you have specified `vmin` and `vmax` for pcolor, if you want to have the same ylim, you can try supply a `levels` parameter to the `contourf` call. – CT Zhu Sep 09 '18 at 01:51