# Reflowing Axes

Dynamically adding Axes to a Figure

At the prompting of a user on Matplotlib’s gitter channel I wrote the following example:

```
import matplotlib.pyplot as plt
import numpy as np
from itertools import count
from matplotlib.gridspec import GridSpec
def reflow_gen(fig):
# we own this figure now so clear it
fig.clf()
# running count of the number of axes
axcount = count(1)
# the shape of the grid
row_guess = col_guess = 0
# the current GridSpec object
gs = None
# we are a generator, so loop forever
while True:
# what number is this Axes?
j = next(axcount)
# do we need to re-flow?
if j > row_guess * col_guess:
# Find the smallest square that will work
col_guess = row_guess = int(np.ceil(np.sqrt(j)))
# and then drop fully empty rows
for k in range(1, row_guess):
if (row_guess - 1) * col_guess < j:
break
else:
row_guess -= 1
# Create the new gridspec object
gs = GridSpec(row_guess, col_guess, figure=fig)
# for each of the axes, adjust it to use the new gridspec
for n, ax in enumerate(fig.axes):
ax.set_subplotspec(gs[*np.unravel_index(n, (row_guess, col_guess))])
# resize the figure to have ~ 3:4 ratio and keep the Axes fixed
fig.set_size_inches(col_guess * 4, row_guess * 3)
# Add the new axes to the Figure at the next open space
new_ax = fig.add_subplot(gs[*np.unravel_index(j - 1, (row_guess, col_guess))])
# hand the Axes back to the user
yield new_ax
# make a Figure
fig = plt.figure(layout='constrained')
# set up the generator
ax_gen = reflow_gen(fig)
for j in range(5):
# get an Axes
ax = next(ax_gen)
ax.set_title(f'Axes {j}')
# fig.savefig(f'dynamic_axes_figs-axes_{j}.svg')
plt.show()
```

**1 axes (1x1)**

**2 axes (2x1)**

**3 axes (2x2)**

**4 axes (2x2)**

**5 axes (3x2)**

and so on up to as many *Axes* as you want to add. Note that the Figure is
getting bigger as more Axes are added so if using this interactively the window
will grow.

I am not sure that this is general enough to add to Matplotlib, but it is a
cute example of how generators can be useful. One concern with this code is
that the generator will keep the *Figure* object alive which may complicate
resource management. There are also some questions for me about what the API
should be. As written the resizing and target aspect ratio behavior is fixed,
I think it is reasonable for users to be able to control both. Additional, the
scheme for growing the grid and selecting which slots to fill at a given grid
size and fill factor could be elaborated. It might also be interesting to
promote the generator to a full generator
co-routine to be able to pass arguments the Axes
creation step (to set projections and such).