1
images = wcs_request.get_data()  # get image data
fig, axs = plt.subplots((len(images) + (6 - 1)) // 6, 6, figsize=(20, 20),
                        gridspec_kw={'hspace': 0.0, 'wspace': 0.0})

total = ((len(images) + (6 - 1)) // 6) * 6

for idx, (image, time) in enumerate(zip(images, wcs_request.get_dates())):
    # Plot bbox
    axs.flat[idx].imshow(image)
    # Set title
    axs.flat[idx].set_title(time.date().strftime("%d %B %Y"), fontsize=10, fontweight='bold')

# delete plots which have no data
for idx in range(len(images), total):
    fig.delaxes(axs.flat[idx])

plt.suptitle(id, fontsize=12, fontweight='bold')
# fig.tight_layout(pad=0, h_pad=.1, w_pad=.1)
# fig.subplots_adjust(wspace=0, hspace=0)
plt.savefig(dir_out / f'{id}_map.png', dpi=300)
plt.close()

When I run the code above, I get a subplot with much larger vertical blank space than I want. How can I fix it? I already set wspace and hspace to 0.0

enter image description here

user308827
  • 21,227
  • 87
  • 254
  • 417
  • aren't you deleting axes that don't have data? therefore creating the white space? – Derek Eden Dec 09 '20 at 03:13
  • I am deleting them since they do not have any data. Is there a way to not plot empty plots and also not have that empty space? – user308827 Dec 09 '20 at 03:20
  • 3
    the problem is that you're creating a grid of axes in your plot, plotting in some and not others, then deleting the empty ones..you'll always be left with the blank space because you made that axes to begin with before you cleared it... the only way would be to compute beforehand how many axes you actually need...then only create those and plot on those – Derek Eden Dec 09 '20 at 04:17

2 Answers2

1

Well, there are many ways to generate a "nice" array of subplots; but assuming that your goal is to, e.g. create two rows of images where len(images)=10:

import matplotlib.pyplot as plt

images=range(10)

## assuming you want e.g.  axes on your first row:
ncols = 6
# figure out how many plots will fall into the last row using modulo
ncols_last = (len(images) % ncols)
# and (if mod > 0 !) add one to the floor operation here:
nrows = (len(images) // ncols ) + (ncols_last > 0)

fig = plt.figure()
axes={}
for i in range(len(images)):
    # note that for some reason, add_subplot() counts from 1, hence we use i+1 here
    axes[i] = fig.add_subplot(nrows,ncols,i+1)

# add some content    
for i,ax in axes.items():
    ax.text(0,0,i)
    ax.set_xlim(-1,1)
    ax.set_ylim(-1,1)
    
plt.show()

Which should give you 6 plots on the first row and 4 on the second. You should be able to add your plot content like this:

for idx, (image, time) in enumerate(zip(images, wcs_request.get_dates())):
    # Plot bbox
    axes[idx].imshow(image)
    # Set title
    axes[idx].set_title(time.date().strftime("%d %B %Y"), fontsize=10, fontweight='bold')

Or alternatively, using gridspec in order to get access to further layout options:

import matplotlib.pyplot as plt
from matplotlib import gridspec

images=range(10)

ncols = 6
ncols_last = (len(images) % ncols)
nrows = (len(images) // ncols ) + (ncols_last > 0)

fig = plt.figure()
axes = {}
gs = gridspec.GridSpec(nrows, ncols,
    left=0.1,right=.9,
    bottom=0.1,top=.9,
    wspace=0.25,hspace=0.3,
)

for i,(r,c) in enumerate([(r,c) for r in range(nrows) for c in range(ncols)]):
    if i < len(images):
        print(f"axes[{i}]: relates to the gridspec at index ({r},{c})")
        axes[i] = fig.add_subplot(gs[r,c])

for i,ax in axes.items():
    ax.text(0,0,i)
    ax.set_xlim(-1,1)
    ax.set_ylim(-1,1)

plt.show()
Asmus
  • 5,117
  • 1
  • 16
  • 21
0

You may want to check out subplots_adjust, which let you specify:

The height of the padding between subplots, as a fraction of the average axes height.

fig, axs = plt.subplots(2,1)
fig.subplots_adjust(hspace=0.0)

So with hspace=0 there is no spacing at all: hspace

max
  • 3,915
  • 2
  • 9
  • 25