Description
Problem
Figures used in publications often consist of multiple panels. Matplotlib provides (amazing, ever-growing) functionality for creating and arranging multiple axes within a figure. When preparing a multi-panel figure for publication, you often need to label each panel so you can reference the individual subplots. It is common to use letters near the upper-left corner of each subplot.
(For an example five-panel figure and caption, see the last figure on https://www.internationalscienceediting.com/how-to-write-a-figure-caption/)
While Matplotlib provides much functionality for arranging axes, calling, e.g., plt.annotate
to manually place every panel label is tedious. The Transformations Tutorial shows an example of manually labeling panels. I am not aware of an existing automatic solution.
While not all Matplotlib users are making figures for publication, many are. Given how common it is to label panels for publication figures, I believe it is worth making panel labeling more convenient.
Proposed Solution
I propose adding a convenience function letter_subplots
to Matplotlib that takes a list of axes and adds letters automatically. Automatic lettering supports common journal formats (uppercase bold letters, lowercase letters in parentheses, etc.) or a list of arbitrary letters can be used.
Here is a gist of my letter_subplots
: https://gist.github.com/bagrow/e3fd0bcfb7e107c0471d657b98ffc19d
A user can also change the position of labels, even setting a different position for each. Additional keyword arguments are passed to annotate
.
I have used this function myself for several years and find it extremely helpful.
Here are some example uses (from the docstring):
Defaults:
>>> fig, axes = plt.subplots(1,3)
>>> letter_subplots() # boldfaced A, B, C
Common labeling schemes inferred from the first letter:
>>> fig, axes = plt.subplots(1,4)
>>> letter_subplots(letters='(a)') # panels labeled (a), (b), (c), (d)
Fully custom lettering:
>>> fig, axes = plt.subplots(2,1)
>>> letter_subplots(axes, letters=['(a.1)', '(b.2)'], fontweight='normal')
Per-axis offsets:
>>> fig, axes = plt.subplots(1,2)
>>> letter_subplots(axes, xoffset=[-0.1, -0.15])
I understand that choosing the right defaults is critical. I like using uppercase bold letters, but the default should probably be whatever is most common across publications or otherwise determined through the same process as any of Matplotlib's style defaults.