TornadoEric
TornadoEric

Reputation: 431

Force CartoPy Map To Fill Entire GridSpec Row

I am using GridSpec and Subplots in combination with CartoPy to make a custom multi-line title region for generated plots. The code below generates the following figure, please note that for efficiency, I've excluded extraneous lines that format the map, colorbar, and place shapefiles.

The Code

fig = plt.figure(figsize=(14,8))
gs = gridspec.GridSpec(ncols=1, nrows=2, height_ratios=[0.15, 3.00])
gs.update(wspace=0.00, hspace=0.00)

ax1 = fig.add_subplot(gs[0, :])
plt.text(0.00, 0.90, "Left Title Line One", fontsize=15, fontproperties=medprop)
plt.text(0.00, 0.20, "Left Title Line Two", fontsize=15, fontproperties=lgtprop)
plt.text(1.00, 1.00, "Right Title Line One", fontsize=15, ha='right', fontproperties=medprop)
plt.text(1.00, 0.20, "Right Title Line Two", fontsize=15, ha='right', fontproperties=lgtprop)
ax2 = fig.add_subplot(gs[1, :], projection=crs.LambertConformal())
ax2.set_extent(region, crs=crs.LambertConformal())
ax2.set_adjustable('datalim')

im = ax2.pcolormesh(xgrid, ygrid, data.variable.data[0], cmap=cmap, norm=norm, alpha=0.90)
plt.colorbar(im, ax=ax2, pad=0.01, ticks=ticks, aspect=40)
fig.tight_layout()

The Generated Figure

Generated Figure

The figure generates successfully, however note that the plot itself does not fill the entire width of the second subplot defined after GridSpec is declared. I've narrowed down the issue to the plot not filling the axes as desired.

Previously, I've tried using ax2 = plt.axes([0.25, 0.05, 0.95, 0.9],projection=crs.LambertConformal()), however this adds a properly constrained plot (with regards to the axes bounds) over both GridSpec rows and is not confined to the second row. What steps can I take to properly either a) fill the width of the second GridSpec row or b) shorten the width of the first row to match the second?

Upvotes: 0

Views: 204

Answers (1)

Rutger Kassies
Rutger Kassies

Reputation: 64453

It's hard to replicate this without all the missing variables you're using. But I suspect gridspec does exactly what you want in this case, except you then adjust the extent of your second axes (the map) when you add the colorbar.

ax : `~matplotlib.axes.Axes`, list of Axes, optional
    One or more parent axes from which space for a new colorbar axes will be
    stolen, if *cax* is None.  This has no effect if *cax* is set.

If you don't want that, you should probably include the axes for the colorbar (the cax keyword) when creating the original layout. Or carefully create a new/separate axes that doesn't alter the existing ones from gridspec.

An easy workaround might be to provide both axes when creating the colorbar, that way both get modified the same way. A side effect is that the colorbar gets aligned with respect to both, which may or may not be what you want aesthetically. For example:

fig = plt.figure(figsize=(10, 5))
gs = mpl.gridspec.GridSpec(ncols=1, nrows=2, height_ratios=[0.25, 3.00])
gs.update(wspace=0.0, hspace=0.0, top=1, bottom=0, left=0, right=1)

ax1 = fig.add_subplot(gs[0, :])
ax1.text(0.00, 0.90, "Left Title Line One", fontsize=15)
ax1.text(0.00, 0.20, "Left Title Line Two", fontsize=15)
ax1.text(1.00, 1.00, "Right Title Line One", fontsize=15, ha='right')
ax1.text(1.00, 0.20, "Right Title Line Two", fontsize=15, ha='right')
ax1.axis("off")

ax2 = fig.add_subplot(gs[1, :], projection=crs.PlateCarree())
im = ax2.imshow(np.random.rand(16, 32), cmap="Blues", extent=[-180, 180, 90, -90])

cb = fig.colorbar(im, ax=[ax1, ax2], pad=0.01, shrink=0.5)

enter image description here

Upvotes: 1

Related Questions