When we want to place text, annotations, or other graphical elements on a Matplotlib plot, there’s a question of what coordinates we mean. Put a label at on the data axes and put a label 50% across, 95% up the chart mean different things, and Matplotlib supports several coordinate systems plus a transform mechanism for converting between them.

The systems worth knowing:

Data coordinates. Positions are in the same units as the data being plotted. (3.5, 0.7) means in whatever units the x-axis uses, in whatever units the y-axis uses. The transform object is ax.transData. This is the default for drawing commands like plot and scatter.

Axes coordinates. Run from (0, 0) at the bottom-left of the Axes to (1, 1) at the top-right. Normalized — doesn’t depend on the data ranges. Put a label at axes-coordinates (0.5, 0.95) always means centered horizontally, near the top, regardless of the data. The transform is ax.transAxes.

Figure coordinates. Run from (0, 0) at the bottom-left of the entire Figure to (1, 1) at the top-right. Put a watermark at figure-coordinates (0.5, 0.5) always means the center of the page. The transform is fig.transFigure.

To place text using a particular transform, pass the transform into the call:

ax.text(0.5, 0.5, "Hello",
        transform=ax.transAxes,
        ha='center', va='center')

ha and va are horizontal and vertical alignment — 'center' aligns the text’s center on the given coordinates, 'left' aligns its left edge, and so on. The result is a string Hello centered in the Axes, regardless of the data plotted in it.

There are also blended systems like ax.get_xaxis_transform(), which uses data coordinates on the x-axis and axes coordinates on the y-axis. A vertical line drawn with this transform spans the full height of the Axes regardless of the data range — useful for marking event times on a time-series plot.

The Matplotlib transform machinery is more general than these three: any transform can be composed with any other, custom transforms can be built, and the same mechanism handles inches-on-paper and pixel coordinates for finer-grained control. For everyday plotting, transData, transAxes, and transFigure cover almost everything.