Combine two matplotlib Figures, side by side, high quality

Viewed 706

I produced two matplotlib Figures, at size of 1000x1000. Each of the figures is 4x4 subplots based figure. I want one figure at size of 1000x2000 (width is 2000).

fig1
<Figure size 1000x1000 with 4 Axes>

fig2
<Figure size 1000x1000 with 4 Axes>

Now I want to combine them together.

I've searched many references: How to make two plots side-by-side using Python?

Plotting two figures side by side

Adding figures to subplots in Matplotlib

They are not relevant because mostly they suggest to change the way the initial plots were created. I don't want to change it - I want to use the Figure as is.

I just need to place Fig1 to the left of Fig2. Not changing the way Fig1 or Fig2 were created.

I also tried using PIL method: https://note.nkmk.me/en/python-pillow-concat-images/ However it was lower quality

2 Answers

You can render your figures to arrays using the agg backend. Then concat the arrays side by side and switch back to your normal backend to show the result:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

backend = mpl.get_backend()
mpl.use('agg')

dpi = 100
fig1,_ = plt.subplots(2,2, figsize=(1000/dpi, 1000/dpi), dpi=dpi)
fig1.suptitle('Figure 1')
fig2,_ = plt.subplots(2,2, figsize=(1000/dpi, 1000/dpi), dpi=dpi)
fig2.suptitle('Figure 2')

c1 = fig1.canvas
c2 = fig2.canvas

c1.draw()
c2.draw()

a1 = np.array(c1.buffer_rgba())
a2 = np.array(c2.buffer_rgba())
a = np.hstack((a1,a2))

mpl.use(backend)
fig,ax = plt.subplots(figsize=(2000/dpi, 1000/dpi), dpi=dpi)
fig.subplots_adjust(0, 0, 1, 1)
ax.set_axis_off()
ax.matshow(a)

enter image description here

Not directly merging two seperate figures, but I succeeded achieving the final goal by using this reference: https://matplotlib.org/devdocs/gallery/subplots_axes_and_figures/subfigures.html

That's the code I needed:

fig = plt.figure(constrained_layout=True, figsize=(20, 11))
titles_size = 25
labels_size = 18
subfigs = fig.subfigures(1, 2, wspace=0.02)
subfigs[0].suptitle('Title 1', fontsize=titles_size)
subfigs[1].suptitle('Title 2', fontsize=titles_size)

axsLeft = subfigs[0].subplots(2, 2)
axsRight = subfigs[1].subplots(2, 2)

for ax_idx, ax in enumerate(axsLeft.reshape(-1)):
    ax.grid(False)
    ax.set_xticklabels([])
    ax.set_yticklabels([])
    ax.axes.xaxis.set_visible(False)
    ax.axes.yaxis.set_visible(False)
for ax_idx, ax in enumerate(axsRight.reshape(-1)):
    ax.grid(False)
    ax.set_xticklabels([])
    ax.set_yticklabels([])
    ax.axes.xaxis.set_visible(False)
    ax.axes.yaxis.set_visible(False)
plt.show()

result

Related