How to combine gridspec with plt.subplots() to eliminate space between rows of subplots

I am trying to plot multiple images in subplots and either eliminate the space between subplots (horizontal and vertical) or control it. I tried to use the suggestion in How to Use GridSpec.... I also tried here but they are not using subplots(): space between subplots I am able to eliminate the horizontal space but not the vertical space with what I am doing in the code below. Please do not mark as duplicate as I have tried the other posts and they do not do what I want. My code is shown below. Maybe there is another keyword argument that I need in the gridspec_kw dictionary? I want to use plt.subplots() not plt.subplot() for this. In case it matters, the images are not square they are rectangular. I also tried adding f.tight_layout(h_pad=0,w_pad=0) before plt.show() but it did not change anything.

def plot_image_array_with_angles(img_array,correct_angles,predict_angles,
                              fontsize=10,figsize=(8,8)):
'''
Imports:
    import matplotlib.gridspec as gridspec
    import numpy as np
    import matplotlib.pyplot as plt
'''
num_images = len(img_array)
grid = int(np.sqrt(num_images))  # will only show all images if square
#f, axarr = plt.subplots(grid,grid,figsize=figsize)
f, axarr = plt.subplots(grid,grid,figsize=figsize,
                      gridspec_kw={'wspace':0,'hspace':0})
im = 0
for row in range(grid):
    for col in range(grid):
        axarr[row,col].imshow(img_array[im])
        title = 'cor = ' + str(correct_angles[im]) + '  pred = ' + str(predict_angles[im])
        axarr[row,col].set_title(title,fontsize=fontsize)
        axarr[row,col].axis('off')  # turns off all ticks
        #axarr[row,col].set_aspect('equal')
        im += 1
plt.show()
return

Solution 1:

The aspect ratio of an imshow plot is automatically set such that pixels in the image are squared. This setting is stronger than any of the subplots_adjust or gridspec settings for spacing. Or in other words you cannot directly control the spacing between subplots if those subplots have their aspect set to "equal".

First obvious solution is to set the image aspect to automatic ax.set_aspect("auto"). This solves the problem of subplot spacing, but distorts the images.

The other option is to adjust the figure margins and the figure size such that the spacing between the subplots is as desired.

Let's say figh and figw are the figure height and width in inch, and s the subplot width in inch. The margins are bottom, top, left and right (relative to figure size) and the spacings hspace in vertical and wspace in horizontal direction (relative to subplot size). The number of rows is denoted n and the number of columns m. The aspect is the ratio between subplot (image) height and width (aspect = image height / image width).

Then the dimensions can be set via

fig, axes = plt.subplots(nrows=n, ncols=m, figsize=(figwidth, figheight))
plt.subplots_adjust(top=top, bottom=bottom, left=left, right=right, 
                        wspace=wspace, hspace=hspace)

The respective values can be calculated according to:

enter image description here

Or, if the margins are the same:

enter image description here

An example:

import matplotlib.pyplot as plt

image = plt.imread("https://i.stack.imgur.com/9qe6z.png")
aspect = image.shape[0]/float(image.shape[1])
print aspect
n = 2 # number of rows
m = 4 # numberof columns
bottom = 0.1; left=0.05
top=1.-bottom; right = 1.-left
fisasp = (1-bottom-(1-top))/float( 1-left-(1-right) )
#widthspace, relative to subplot size
wspace=0.15  # set to zero for no spacing
hspace=wspace/float(aspect)
#fix the figure height
figheight= 3 # inch
figwidth = (m + (m-1)*wspace)/float((n+(n-1)*hspace)*aspect)*figheight*fisasp

fig, axes = plt.subplots(nrows=n, ncols=m, figsize=(figwidth, figheight))
plt.subplots_adjust(top=top, bottom=bottom, left=left, right=right, 
                    wspace=wspace, hspace=hspace)

for ax in axes.flatten():
    ax.imshow(image)
    ax.set_title("title",fontsize=10)
    ax.axis('off')

plt.show()

enter image description here