12

I'm somewhat new to matplotlib. What I'm trying to do is write code that saves several figures to eps files, and then generates a composite figure. Basically what I'd like to do is have something like

import matplotlib.pyplot as plt
from matplotlib import gridspec

def my_plot_1():
    fig = plt.figure()
    ...
    return fig

def my_plot_2():
    fig = plt.figure()
    ...
    return fig

def my_combo_plot(fig1,fig2):
    fig = plt.figure()
    gs = gridspec.GridSpec(2,2)
    ax1 = plt.subplot(gs[0,0])
    ax2 = plt.subplot(gs[0,1])
    ax1 COPY fig1
    ax2 COPY fig2
    ...

where then later I could do something like

my_combo_plot( my_plot_1() , my_plot_2() )

and have all the data and settings get copied from the plots returned by the first two functions, but I can't figure out how this would be done with matplotlib.

user202729
  • 3,358
  • 3
  • 25
  • 36
Alex Z
  • 1,449
  • 4
  • 20
  • 29
  • It's possible to move them around (to duplicate them you can pickle then unpickle). https://stackoverflow.com/a/46906599/5267751 shows how to move it from one figure to another, but I've yet to figure out how to put it in a particular subplot – user202729 Jun 26 '22 at 02:21

2 Answers2

7

Since pyplot kind of works like a state machine, I'm not sure if what you are asking for is possible. I would instead factor out the drawing code, something like this:

import matplotlib.pyplot as plt

def my_plot_1(ax=None):
    if ax is None:
        ax = plt.gca()
    ax.plot([1, 2, 3], 'b-')

def my_plot_2(ax=None):
    if ax is None:
        ax = plt.gca()
    ax.plot([3, 2, 1], 'ro')

def my_combo_plot():
    ax1 = plt.subplot(1,2,1)
    ax2 = plt.subplot(1,2,2)
    my_plot_1(ax1)
    my_plot_2(ax2)
wim
  • 338,267
  • 99
  • 616
  • 750
  • 1
    This is the best solution IMHO. I just wanted to add that, now that figures are picklable, technically it is also possible to copy a figure instance - you can even do this from one backend to another. – pelson Apr 12 '13 at 16:27
  • 4
    This might be a quick work around but is not an answer. If you have "plotting instructions" that take a lot of time, this solution is not feasible. Say that I have a 3D plot and want to show, in 3 subplots, XZ,YZ and XY views. In principle you could use the same plot and change the view. With this solution, you simply plot 3 times instead of once and change the view. (Unfortunately, I also don't know how to achieve this). Someone? – user989762 Mar 26 '14 at 00:23
0

Using the answer https://stackoverflow.com/a/46906599/5267751 it's possible to move the axes from one figure to other (using pickle it's also possible to keep the old figure).

Add set_subplotspec to position the resulting axes:

import matplotlib.pyplot as plt
from matplotlib import gridspec

def my_plot_1():
    fig = plt.figure()
    plt.plot([1, 2, 3], 'b-')
    return fig

def my_plot_2():
    fig = plt.figure()
    plt.plot([3, 2, 1], 'ro')
    return fig

fig1 = my_plot_1()
fig2 = my_plot_2()

def my_combo_plot(fig1,fig2):
    fig = plt.figure()
    gs = gridspec.GridSpec(2,2)

    ax1 = fig1.axes[0]
    ax1.remove()
    ax1.figure = fig
    fig.add_axes(ax1)
    ax1.set_subplotspec(gs[0, 0])

    ax2 = fig2.axes[0]
    ax2.remove()
    ax2.figure = fig
    fig.add_axes(ax2)
    ax2.set_subplotspec(gs[0, 1])

    plt.close(fig1)
    plt.close(fig2)

my_combo_plot( my_plot_1() , my_plot_2() )

plt.show()

The code assumes that each figure contains exactly one axes, however.

user202729
  • 3,358
  • 3
  • 25
  • 36