Search code examples
pythonmatplotlibsubplotnilearn

Removing/Hiding empty subplots in matplotlib, when plotting a flexible grid


I am using nilearn to plot a range of cuts along a axis through a 3D image file of a brain. My goal is to make a flexible function, in which I can change the number of rows, cols and coordinate range of the cuts as I please. The reason for this, is that I can generate a .png file and use it for visualization, e.g. directly in a paper.

So basically I use a nested loop, to generate a grid of matplotlib subplots and fill them with the brain-images. Those come from one line of code from a nilearn-function, so that's not the issue.

My question is: Is there a way to detect and hide/delete empty subplots? The problem is, that now the empty subplots come wit an error message, which seems to mess with the .png file it returns. Also the empty subplots are shown in the .png file, which should not be the case.

Here is my code:

i = -55
j = 55
rows = 5
cols = 5
k = np.ceil((abs(i)+j)/(rows*cols))
cuts = np.arange(i,j,k)
rsn_img = 'rsn_img.png'

fig, axes = plt.subplots(rows, cols, figsize=(15,10))

for r in range(rows):
    for c in range(cols):
        display=plotting.plot_stat_map(rsn_four, display_mode='x', axes=axes[r,c], cut_coords=[cuts[r*cols+c]], threshold=2)
        
        print(f'plotting at index [ {r} , {c}]')
    display.savefig(rsn_img)

This is the output: enter image description here

I the subplots that are not filled, should be removed. Thanks for your help in advance!


Solution

  • I assume you know the number of images N that you want to plot.

    This is how I would write it:

    i = -55
    j = 55
    cols = 5
    rows = 5
    k = np.ceil((abs(i)+j)/(rows*cols))
    cuts = np.arange(i,j,k)
    N = len(cuts)
    
    fig, axs = plt.subplots(rows, cols)
    for ax,cut in zip(axs.flat,cuts):
        display=plotting.plot_stat_map(rsn_four, display_mode='x', axes=ax, cut_coords=cut, threshold=2)
    # remove unused axes
    for ax in axs.flat[N:]:
        ax.remove()