Reputation: 187
I have 4 maps of different values that I would like to plot with matplotlib Basemap together as 4 subplots in 1 figure, each with its own colorbar. But my efforts to set colorbar and subplot sizes and orientations seem to fail (see the code below). Does anybody know what I am doing wrong? Is it not possible to customize subplot and colorbar settings when using Basemap?
import math
import matplotlib.cm as cm
import matplotlib.colors as colors
import matplotlib.image as mpimg
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import numpy.ma as ma
import numpy as np
import pylab
# Create Variables:
B = np.full((4,60,360), np.nan)
B[0] = np.random.randint(16, size=(60, 360)) + 291
B[1] = np.random.randint(201, size=(60, 360)) - 100
B[2] = np.random.randint(56, size=(60, 360)) - 50
B[3] = np.random.randint(46, size=(60, 360))
# Colorbar Boundary Definitions:
cmap_1 = cm.jet
cmap_2 = cm.BrBG
cmap_3 = cm.hot
cmap_4 = cm.CMRmap_r
B_plot = np.ma.array ( B, mask=np.isnan(B))
bounds_B = []
norm_B = []
for b in np.arange(4):
bounds_B.append(b)
norm_B.append(b)
bounds_B[0] = np.arange(291, 306, 1)
bounds_B[1] = np.arange(-100, 110, 10)
bounds_B[2] = np.arange(-50, -7.5, 2.5)
bounds_B[3] = np.arange(0, 47.5, 2.5)
norm_B[0] = mpl.colors.BoundaryNorm(bounds_B[0], cmap_1.N)
norm_B[1] = mpl.colors.BoundaryNorm(bounds_B[1], cmap_2.N)
norm_B[2] = mpl.colors.BoundaryNorm(bounds_B[2], cmap_3.N)
norm_B[3] = mpl.colors.BoundaryNorm(bounds_B[3], cmap_4.N)
lat = (-1) * (np.arange(-29.5, 30.5, 1))
lon = np.arange(0.5, 360.5, 1)
llc_LON = 0.5
urc_LON = 359.5
llc_LAT = -29.5
urc_LAT = 29.5
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(9, 5))
# Variable 1
m1 = Basemap(projection='cyl', llcrnrlon=llc_LON, urcrnrlon=urc_LON, llcrnrlat=llc_LAT, urcrnrlat=urc_LAT, resolution='c')
m1.drawcoastlines(color='k')
m1.fillcontinents(color='white') # mask land mass
lons, lats = np.meshgrid(lon,lat)
x, y = m1(lons,lats)
m1.pcolor(x, y, B_plot[0], cmap=cmap_1, norm=norm_B[0])
img_1 = m1.pcolor(x, y, B_plot[0], cmap=cmap_1, norm=norm_B[0])
axes[0, 0].set_title('Variable 1')
axes[0, 0].set_xlim(llc_LON, urc_LON)
axes[0, 0].set_xticks([0, 45, 90, 135, 180, 225, 270, 315, 360], ['0', '45E', '90E', '135E', '180', '135W', '90W', '45W', '0']) # 0E to 360E
axes[0, 0].set_ylim(llc_LAT, urc_LAT)
axes[0, 0].set_yticks([-30, -15, 0, 15, 30], ['30S', '15S', '0', '15N', '30N']) # 30S to 30N
axes[0, 0].set_ylabel('Latitude')
plt.grid()
# Variable 2
m2 = Basemap(projection='cyl', llcrnrlon=llc_LON, urcrnrlon=urc_LON, llcrnrlat=llc_LAT, urcrnrlat=urc_LAT, resolution='c')
m2.drawcoastlines(color='k')
m2.fillcontinents(color='white') # mask land mass
lons, lats = np.meshgrid(lon,lat)
x, y = m2(lons,lats)
m2.pcolor(x, y, B_plot[1], cmap=cmap_2, norm=norm_B[1])
img_2 = m2.pcolor(x, y, B_plot[1], cmap=cmap_2, norm=norm_B[1])
axes[0, 1].set_title('Variable 2')
axes[0, 1].set_xlim(llc_LON, urc_LON)
axes[0, 1].set_xticks([0, 45, 90, 135, 180, 225, 270, 315, 360], ['0', '45E', '90E', '135E', '180', '135W', '90W', '45W', '0']) # 0E to 360E
axes[0, 1].set_ylim(llc_LAT, urc_LAT)
axes[0, 1].set_yticks([-30, -15, 0, 15, 30], ['30S', '15S', '0', '15N', '30N']) # 30S to 30N
plt.grid()
# Variable 3
m3 = Basemap(projection='cyl', llcrnrlon=llc_LON, urcrnrlon=urc_LON, llcrnrlat=llc_LAT, urcrnrlat=urc_LAT, resolution='c')
m3.drawcoastlines(color='k')
m3.fillcontinents(color='white') # mask land mass
lons, lats = np.meshgrid(lon,lat)
x, y = m3(lons,lats)
m3.pcolor(x, y, B_plot[2], cmap=cmap_3, norm=norm_B[2])
img_3 = m3.pcolor(x, y, B_plot[2], cmap=cmap_3, norm=norm_B[2])
axes[1, 0].set_title('Variable 3')
axes[1, 0].set_xlim(llc_LON, urc_LON)
axes[1, 0].set_xticks([0, 45, 90, 135, 180, 225, 270, 315, 360], ['0', '45E', '90E', '135E', '180', '135W', '90W', '45W', '0']) # 0E to 360E
axes[1, 0].set_ylim(llc_LAT, urc_LAT)
axes[1, 0].set_yticks([-30, -15, 0, 15, 30], ['30S', '15S', '0', '15N', '30N']) # 30S to 30N
axes[1, 0].set_ylabel('Latitude')
plt.grid()
# Variable 4
m4 = Basemap(projection='cyl', llcrnrlon=llc_LON, urcrnrlon=urc_LON, llcrnrlat=llc_LAT, urcrnrlat=urc_LAT, resolution='c')
m4.drawcoastlines(color='k')
m4.fillcontinents(color='white') # mask land mass
lons, lats = np.meshgrid(lon,lat)
x, y = m4(lons,lats)
m4.pcolor(x, y, B_plot[3], cmap=cmap_4, norm=norm_B[3])
img_4 = m4.pcolor(x, y, B_plot[3], cmap=cmap_4, norm=norm_B[3])
axes[1, 1].set_title('Variable 4')
axes[1, 1].set_xlim(llc_LON, urc_LON)
axes[1, 1].set_xticks([0, 45, 90, 135, 180, 225, 270, 315, 360], ['0', '45E', '90E', '135E', '180', '135W', '90W', '45W', '0']) # 0E to 360E
axes[1, 1].set_ylim(llc_LAT, urc_LAT)
axes[1, 1].set_yticks([-30, -15, 0, 15, 30], ['30S', '15S', '0', '15N', '30N']) # 30S to 30N
plt.grid()
plt.subplots_adjust(bottom=0.1, hspace=0.2)
colorbar_1 = fig.add_axes([0.1, 0.48, 0.30, 0.015])
fig.colorbar(img_1, cax=colorbar_1, orientation="horizontal", label='Unit 1', ticks=[291, 293, 295, 297, 299, 301, 303, 305])
colorbar_2 = fig.add_axes([0.55, 0.48, 0.30, 0.015])
fig.colorbar(img_2, cax=colorbar_2, orientation="horizontal", label='Unit 2', ticks=[-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100])
plt.subplots_adjust(bottom=0.05, right=0.80, left=0.21, hspace=0.2)
colorbar_3 = fig.add_axes([0.1, 0.08, 0.30, 0.015])
fig.colorbar(img_3, cax=colorbar_3, orientation="horizontal", label='Unit 3', ticks=[-50, -45, -40, -35, -30, -25, 20, -15, -10])
colorbar_4 = fig.add_axes([0.55, 0.08, 0.30, 0.015])
fig.colorbar(img_4, cax=colorbar_4, orientation="horizontal", label='Unit 4', ticks=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45])
plt.show()
Upvotes: 1
Views: 1856
Reputation: 5502
The main issue is how you define the plotbar
. Here, I do it with the current axis in a for
loop. Also, the xthick
are not displayed, to display them I used set_xticklabels
.
Then, I cleaned your code since you're mostly doing 4 times the same thing.
import math
import matplotlib.cm as cm
import matplotlib.colors as colors
import matplotlib.image as mpimg
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import numpy.ma as ma
import numpy as np
import pylab
# Create Variables:
B = np.array([np.random.randint(16, size=(60, 360)) + 291,
np.random.randint(201, size=(60, 360)) - 100,
np.random.randint(56, size=(60, 360)) - 50,
np.random.randint(46, size=(60, 360))])
# Colorbar Boundary Definitions:
cmap = [cm.jet, cm.BrBG, cm.hot, cm.CMRmap_r]
B_plot = np.ma.array(B, mask=np.isnan(B))
norm_B = []
bounds_B = [np.arange(291, 306, 1),
np.arange(-100, 110, 10),
np.arange(-50, -7.5, 2.5),
np.arange(0, 47.5, 2.5)]
for b in np.arange(4):
norm_B.append(mpl.colors.BoundaryNorm(bounds_B[b], cmap[b].N))
lat = (-1) * (np.arange(-29.5, 30.5, 1))
lon = np.arange(0.5, 360.5, 1)
llc_LON = 0.5
urc_LON = 359.5
llc_LAT = -29.5
urc_LAT = 29.5
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(9, 5))
thicks = [[291, 293, 295, 297, 299, 301, 303, 305],
[-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100],
[-50, -45, -40, -35, -30, -25, 20, -15, -10],
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]]
lons, lats = np.meshgrid(lon, lat)
for row_ind in range(2):
for col_ind in range(2):
index = row_ind*2+col_ind
current_ax = axes[row_ind, col_ind]
print("row_ind: {0} col_ind: {1} index: {2}".format(row_ind, col_ind, index))
map = Basemap(projection='cyl', llcrnrlon=llc_LON, urcrnrlon=urc_LON,
llcrnrlat=llc_LAT, urcrnrlat=urc_LAT, resolution='c',
ax=current_ax)
map.drawcoastlines(color='k')
map.fillcontinents(color='white') # mask land mass
x, y = map(lons, lats)
img_colors = map.pcolor(x, y, B_plot[index], cmap=cmap[index], norm=norm_B[index])
fig.colorbar(img_colors, ax=current_ax, orientation="horizontal",
label='Unit ' + str(index+1), ticks=thicks[index])
current_ax.set_title('Variable ' + str(index+1))
current_ax.set_xlim(llc_LON, urc_LON)
current_ax.set_xticks([0, 45, 90, 135, 180, 225, 270, 315, 360])
current_ax.set_xticklabels(['0', '45E', '90E', '135E', '180', '135W', '90W', '45W', '0']) # 0E to 360E
current_ax.set_ylim(llc_LAT, urc_LAT)
current_ax.set_yticks([-30, -15, 0, 15, 30]) # 30S to 30N
current_ax.set_yticklabels(['30S', '15S', '0', '15N', '30N'])
current_ax.set_ylabel('Latitude')
fig.suptitle('My maps')
plt.show()
Upvotes: 3