A Practical Guide To The Anatomy Of The Pigeon Framework
The Anatomy Of The Pigeon framework is a set of open-source design patterns created by the team behind SciencePlots and related medical illustration tooling. It standardizes how anatomical figures are structured, labeled, and exported for peer-reviewed journals and textbooks. If you work in scientific visualization at all, you will eventually run into it. At its core, the framework provides a consistent coordinate system and labeling convention for anatomical figures. Instead of every illustrator reinventing their own axis system for a coronal slice or a sagittal view, Anatomy Of The Pigeon defines a shared reference frame. This means your figure can be reused across publications without redrawing the entire layout from scratch. The package includes pre-built figure templates, a labeling engine that handles Greek letters and subscripts automatically, and export functions that push directly to vector formats like PDF and SVG. It is built on top of matplotlib, so if you already know Python you have most of what you need.
How To Get It Set Up
You can find the framework on GitHub. The installation is straightforward if you use pip: pip install anatomy-of-the-pigeon After that, you import it the same way you would any other library:
from anatomy_of_the_pigeon import FigureLayout, LabelEngine I spent about twenty minutes getting mine working on a fresh Ubuntu 22.04 machine. The only hiccup was a dependency conflict with an older version of matplotlib that my university cluster was forcing. I resolved it by pinning to matplotlib 3.8.3 before installing the framework. If you are on a managed research server, check what version of Python and matplotlib is already present. You may need a virtual environment to avoid breaking existing projects.
Get the Full Details

Building A Figure Step By Step
Here is how I typically approach a new anatomical figure using the framework: First, I define the figure layout. The FigureLayout class handles axis positioning, margins, and spacing. You pass it a dictionary describing the structure of your figure. For a single coronal brain slice with a legend inset, my layout dict looked like this: layout = {
"main": {"x": 0.1, "y": 0.15, "w": 0.7, "h": 0.7}, "legend": {"x": 0.82, "y": 0.15, "w": 0.15, "h": 0.3} }
Next, I create the FigureLayout instance and render the base axes: fig = FigureLayout(layout) This takes about three seconds on my machine. The resulting axes are already positioned correctly. You then plot your data on fig.axes["main"] the same way you would on any matplotlib axes.

For labeling, the LabelEngine class is where the framework earns its keep. Instead of manually placing text annotations with relative coordinates, you pass region names and the engine calculates proper placement with collision detection: labels = LabelEngine(fig) labels.add_label("CA1", region="hippocampus_ca1")
labels.add_label(" dentate gyrus ", region="DG") The engine uses a spring-force simulation to avoid overlapping labels. It is not perfect. I encountered a case where two adjacent nuclei in a coronal section kept bouncing between positions every time I reran the script. The workaround was to manually lock one label's position using the fix_anchor parameter, then let the engine resolve the remaining labels around it. Export is trivial:
fig.save("figure.pdf") fig.save("figure.svg") Both come out clean. The PDF version is what I submit to journals. It resolves at vector quality regardless of zoom level, which matters when reviewers want to examine fine structures.

Where The Framework Falls Short
It is not a complete solution. The rendering speed drops noticeably when you move beyond simple 2D layouts. I tried using it for a multi-panel figure with six interconnected 3D volume renders and it took roughly four minutes to generate a single page. For most standard anatomical figures this is fine, but if you are doing high-throughput figure generation it becomes a bottleneck. Another limitation is the labeling collision detection. The spring-force approach works well for five to ten labels. Beyond that, you will spend more time adjusting manual overrides than saving time. I found that capping the auto-label count at eight and handling the rest manually kept my workflow moving at a reasonable pace. The documentation is also incomplete. There are no examples for 3D coordinate systems or for integrating with non-python visualization tools like Blender or ParaView. If your pipeline involves those tools, you are on your own after the initial figure creation step.
When To Use It And When To Skip It
Use Anatomy Of The Pigeon when you need consistent, publication-ready 2D anatomical figures and you are comfortable with Python. It saves me roughly forty-five minutes per figure compared to building everything from scratch in matplotlib alone. That time adds up quickly if you are producing figures for multiple papers in a row. Skip it if you need extensive 3D rendering, if your figures require heavy interactivity, or if your lab standardizes on R or Julia. The framework is Python-only and tightly coupled to matplotlib internals, so porting it elsewhere is not practical. For my own work, I pair it with a custom pre-processing script that takes my segmentation masks from Fiji and converts them into the coordinate format the framework expects. That script alone cuts the data preparation time from about twenty minutes down to three. It is not glamorous but it is the kind of thing that actually matters when you are on a deadline.