1

Possible duplicate of : How to assign a plot to a variable and use the variable as the return value in a Python function but answer did not worked for me.

Consider a figure generated like in this examples: https://networkx.github.io/documentation/networkx-1.9/examples/drawing/four_grids.html

I have a list of figures figs representing graphs, which I want to compose in a layout.


EDITED to address the comment

Note that nx.draw() generates a matplotlib.figure.Figure object.

nx.draw() does not return a matplotlib.figure.Figure object, however I can store the generated figure in a variable, like this:

def graph_to_figure(g):
   fig = plt.figure()
   nx.draw(g,pos,font_size=8)
   plt.close()
   return fig

type(graph_to_figure(g))

>> matplotlib.figure.Figure

so I can generate a list of figures as:

figs = [ graph_to_figure(g), graph_to_figure(g)]

I now want to paginate results to create a pdf.

I tried something like:

plot_num = 221 #2 rows, 2 columns, start from index 1

pagefig = plt.figure(figsize=(10, 10)) 
    for fig in figs:
      pagefig.add_subplot( plot_num)
      plt.imshow(fig)  # return error! any api like plt.add_figure( ) to add the figure to the plot? 
      plot_num += 1

But it will give error, for the image fig cannot be converted in float : it is expecting a real image.

So I tried and looked at the documentation, but caould not figure out how to simply place a matplotlib.figure.Figure object on the grid.

Second attempt

Looking at: Adding figures to subplots in Matplotlib

it shows example making use of subplot:

fig, ax = plt.subplots(2, 1, sharex=True)
plot_fig_1(..., ax[0])
plot_fig_2(..., ax[1])

but instead I a matplotlib.figure object, not a matplotlib.pyplot object..

I may do something like this:

  pagefig.add_subplot( plot_num)

  nx.draw(G,pos,font_size=8)

  plot_num += 1

but I want to add the figure as a variable.

  pagefig.add_subplot( plot_num)

  figs[0] # doesn't work 

  plot_num += 1

How to compose layouts making use of variables referencing to matplotlib.figure.Figure objects?

How to add the variables to a grid ?

Please note I am not using plots, nor images, but figures.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
user305883
  • 1,635
  • 2
  • 24
  • 48
  • 1
    Essentially you are trying to plug one (or several) figure(s) into a new figure. This is not possible with matplotlib. A figure is an entity by itself and cannot be used to compose other figures. However, the premise that `nx.draw()` returns such figure seems to be wrong as well. It should return `None`. Can you verify and correct the question? – ImportanceOfBeingErnest Nov 11 '19 at 23:13

1 Answers1

0

You would need to create a single figure first. You can directly create 4 axes as well and plot to those axes. This should look like as follows (untested):

fig, ax_arr = plt.subplots(2,2)

for ax, g, pos in zip(ax_arr.flat, list_of_g, list_of_pos):
    nx.draw(g, pos, font_size=8, ax=ax)

plt.show()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • thank you for your thought, Oscar Wilde :D. It seems the only way is to generate the drawings in the loop. I wish to use a variable, though. If I replace `nx.draw(g, pos, font_size=8, ax=ax)` with a figure stored with the method described in the question, it won't work: `for ax, fig in zip(ax_arr.flat, figs[:3]): fig # plt.show()` where `figs = [ graph_to_figure(g), ... ,graph_to_figure(g) ` I also tried to overwrite the axes of a the current drawing, like `fig.axes[0] = ax`, but I see empty plots.. I don't know if the drawing is actually rendered, or rendered but off of the subplot. – user305883 Nov 12 '19 at 10:50
  • Yes.As commented already, you cannot add a figure to another figure. The other option would be to save each figure as pdf, then compose the 4 pdfs into a single pdf using some pdf writer program. – ImportanceOfBeingErnest Nov 12 '19 at 11:54
  • I see. It would be a nice functionality though! By the way, I read your profile and super knowledgeable about matplotlib. May I ask you, am I talking to one of the key contributors? – user305883 Nov 12 '19 at 13:39
  • 1
    That functionality would be very very hard to implement due to the transform system that matplotlib is using. But rewriting the transform system would essentially mean to rewrite matplotlib itself. I am member of the dev team and did quite some contributions, but my role is not "key" for the project. – ImportanceOfBeingErnest Nov 12 '19 at 14:17
  • 1
    You can compose nested subplot specs as well, but not after the fact. https://matplotlib.org/3.1.1/tutorials/intermediate/gridspec.html#gridspec-using-subplotspec – Jody Klymak Nov 12 '19 at 15:08