0

I want a grid figure with m rows and n columns to be displayed sharing both x and y axis between subplots, and no whitespace between them. This is easy to achieve with simple plot in matplotlib, as with this code

def plot_me():
    n = 4
    m = 5
    f, axs = plt.subplots(m,n, sharex=True, sharey=True, gridspec_kw=dict(hspace=0, wspace=0))
    x = np.arange(44)
    for i in range(m):
        for j in range(n):
            axs[i,j].plot(np.sin(x*(i*j+1)))

enter image description here

but when I change axs[i,j].plot() to axs[i,j].imshow() then there is a vertical whitespace between the columns, but not a horizontal one! Why is that?

def imshow_me():
    n = 4
    m = 5
    f, axs = plt.subplots(m,n, sharex=True, sharey=True, gridspec_kw=dict(hspace=0, wspace=0))
    for i in range(m):
        for j in range(n):
            axs[i, j].imshow(np.random.random((100, 100)))

enter image description here

I also tried with f.subplots_adjust(wspace=0, hspace=0) but with the same result. And also with mosaic plot, and again in one axis there is no whitespace, while in the other is.

I'm using Python 3.11.2 in visual studio code 1.78.2, matplotlib 3.7.1

Thanks in advance.

EDIT, as with @jared linked thread Matplotlib adjust image subplots hspace and wspace does not raise the specific issue of imshow compared to simple plot, nor are the answerd there satisfactory solving the issue.

What solved the issue for me is using pcolormesh, as per @jared comment. Alternatively, as explained by @gboffi one can force the plot h/w ratio to be exactly 1.5 to avoid whitespaces

fffff
  • 83
  • 9
  • 1
    Are you set on using `imshow`? If it's not an image, use `pcolormesh`. – jared Jun 22 '23 at 21:23
  • ```pcolormesh``` does the trick! Thanks!! still it does not answer the question why ```imshow``` behaves that way, but i can work form here. – fffff Jun 23 '23 at 00:51
  • 1
    Does this answer your question? [Matplotlib adjust image subplots hspace and wspace](https://stackoverflow.com/questions/52661906/matplotlib-adjust-image-subplots-hspace-and-wspace) – jared Jun 23 '23 at 02:32
  • Re the question _"Why `imshow` behaves that way?"_, I have posted an answer below. – gboffi Jun 23 '23 at 09:04
  • @jared thanks for spotting that thread, but it does not satisfactorily address the issue for a bigger than 2x2 grid, as @Arcturus_B comments point out. I think your ```pcolormesh``` suggestion, together with @gboffi is good to answer the question and solves the issue, at least partially – fffff Jun 23 '23 at 14:24

1 Answers1

2

imshow is for images, and images usually are represented in terms of SQUARE pixels.

If an image is 200 px wide and 300 px high, Matplotlib places, let's say, on the screen a rectangle with an aspect ratio of 1.5 (the actual pixel count not being 200x300), and later draws the axes frame, complete with spines, labels etc, fitting the displayed image or, in your case, just the frame.

If so it happens that the aspect ratio (h/w) of the subplots is exactly 1.5, and I mean exactly 1.5 after the figure size, the axes ticks, the tick labels, the titles, etc are taken into account, then everything fits, otherwise...

Ultimately, the unwanted white space is added horizontally if the figsize is too wide or horizontally if the figsize is too tall, as shown in the following example:

import matplotlib.pyplot as plt
mat = [[i for i in range(j, j+10)] for j in range(10)]
fig0, axs0 = plt.subplots(2, 2, edgecolor='k', linewidth=1,
    figsize=(6,2), gridspec_kw=dict(hspace=0, wspace=0))
for ax in axs0.flatten(): ax.imshow(mat)
fig1, axs1 = plt.subplots(2, 2, edgecolor='k', linewidth=1,
    figsize=(4,6), gridspec_kw=dict(hspace=0, wspace=0))
for ax in axs1.flatten(): ax.imshow(mat)
plt.show()

enter image description here

enter image description here


PS In a comment Jared correctly suggested the use of pcolormesh. pcolormesh has a different approach and treats the not-an-image as stretchable, hence it can make it fit inside the elements of the grid.


PS2 In other words, when you use imshow matplotlib fits the subplot around a fixed shape image, when you use pcolormesh Matplotlib distorts the image to fit inside a fixed shape subplot.

gboffi
  • 22,939
  • 8
  • 54
  • 85
  • oks, thanks for knowing the machinery behind ```imshow```, curious to know that the "h/w" ratio has to be *exactly* 1.5!! – fffff Jun 23 '23 at 14:20
  • @fffff Exactly 1.5 in my first example. In general, it depends. – gboffi Jun 23 '23 at 15:08