For each additional level of the square spiral, two sides are added, except for the very last one where only one side is needed. The i,j
positions increment or decrement with 1 at every step, and at each corner the direction is turned 90 degrees.
This is how it could work:
import matplotlib.pyplot as plt
import numpy as np
N = 6
fig = plt.figure(figsize=(16, 18), constrained_layout=True)
spec = fig.add_gridspec(ncols=N * 2 - 1, nrows=N * 2 - 1)
i, j = N - 2 + N % 2, N - 1
dir_i, dir_j = 1, - 1
plot_num = 0
for k in range(1, N + 1):
for _ in range(2): # add two strokes of k subplots (only 1 when k==N)
for _ in range(k):
ax = fig.add_subplot(spec[i, j])
ax.imshow(np.random.rand(3, 3))
ax.set_xlabel(f'{plot_num} [{k}]', fontsize=18)
plot_num += 1
i += dir_i
j += dir_j
if k == N:
break
dir_i, dir_j = -dir_j, dir_i
plt.show()

To copy the original numbering exactly, some concentric squares can be drawn. For odd N
, the last square is quite irregular, with only 2 sides, where the last line jumps to the opposite side and with one square less than the rest.
For the weird numbering of 2 and 3, some renumbering can be introced:
import matplotlib.pyplot as plt
import numpy as np
N = 6
fig = plt.figure(figsize=(16, 18), constrained_layout=True)
spec = fig.add_gridspec(ncols=2 * N - 1, nrows=2 * N - 1)
plot_num = 0
for k in range(2, N + 2, 2):
# i, j = N - 2 + N % 2, N - 1
i, j = N - k + N % 2, N - 1
dir_i, dir_j = 1, - 1
for side in range(4): # add four strokes of k subplots (only 2 when k==N)
for _ in range(k - 1):
ax = fig.add_subplot(spec[i, j])
modified_plot_num = 5 - plot_num if plot_num in (2, 3) else plot_num
ax.imshow(np.random.rand(6, 6), cmap='inferno')
ax.set_xlabel(f'{modified_plot_num} [{k}]', fontsize=18)
plot_num += 1
i += dir_i
j += dir_j
if plot_num == N * N: # for odd N, the very last cell should be skipped
break
if k == N + 1:
if side == 0: # for last side of uneven square: jump to the other side
dir_i, dir_j = -dir_i, -dir_j
i, j = i - 1, 2 * N - 2
elif side == 1:
break
dir_i, dir_j = -dir_j, dir_i
plt.show()
