What are 'matplotlib' "figure points" and how are they determined?
Categories:
Understanding Matplotlib 'Figure Points' and Their Determination

Explore the concept of 'figure points' in Matplotlib, how they relate to coordinate systems, and how to precisely position elements within your plots.
When working with Matplotlib, understanding its various coordinate systems is crucial for precise control over plot elements. Among these, 'figure points' often cause confusion. This article demystifies what figure points are, how they differ from other coordinate systems like 'data coordinates' and 'axes coordinates', and how you can use them to accurately position text, annotations, and other graphical elements within your Matplotlib figures.
Matplotlib's Coordinate Systems: A Hierarchy
Matplotlib employs a hierarchical system of coordinate transformations to render plots. Each level serves a specific purpose and understanding their relationships is key to effective plotting. The primary coordinate systems are:
- Data Coordinates: These are the coordinates of your actual data, as passed to plotting functions like
plot()
,scatter()
, orimshow()
. They are specific to a givenAxes
object. - Axes Coordinates: Normalized coordinates within an
Axes
object, ranging from(0, 0)
at the bottom-left to(1, 1)
at the top-right. These are independent of the data limits and the figure size. - Figure Coordinates: Normalized coordinates within the entire
Figure
object, ranging from(0, 0)
at the bottom-left to(1, 1)
at the top-right. These are independent of the figure's pixel size. - Figure Points: These are absolute coordinates measured in 'points' from the bottom-left corner of the
Figure
. A 'point' is a standard unit of measurement in typography, typically defined as 1/72 of an inch. This system is useful for precise, fixed-size positioning regardless of figure size or DPI.
flowchart TD A[Data Coordinates] --> B["Axes Coordinates (0-1)"] B --> C["Figure Coordinates (0-1)"] C --> D["Figure Points (absolute)"] D --> E[Display Pixels] subgraph Transformation Flow A -- "`Axes.transData`" --> B B -- "`Axes.transAxes`" --> C C -- "`Figure.transFigure`" --> D D -- "`Figure.dpi_scale_trans`" --> E end
Matplotlib's Coordinate Transformation Hierarchy
What Exactly Are 'Figure Points'?
Figure points represent an absolute unit of measurement within the Matplotlib figure. Unlike normalized coordinates (axes or figure coordinates) which scale with the figure size, figure points provide a fixed physical dimension. One 'point' is traditionally defined as 1/72 of an inch. This means if you specify a position at (72, 72)
in figure points, it will always be 1 inch from the bottom-left corner of the figure, regardless of the figure's overall size or resolution (DPI).
This coordinate system is particularly useful when you need to place elements at a precise physical location on the rendered output, such as a logo, a fixed-size legend, or a specific annotation that should not scale with the plot itself. Matplotlib's Figure.dpi
(dots per inch) plays a role in converting these points to pixels for display or saving, but the underlying 'point' unit remains constant.
Using Figure Points for Positioning
While most plotting functions operate in data or axes coordinates, you can explicitly use figure points for positioning. The Figure.transFigure
transformation object is key here. It allows you to transform between figure coordinates (0-1) and figure points. However, for direct placement, you often interact with methods that accept a transform
argument.
For instance, the fig.text()
method, by default, uses figure coordinates. To use figure points, you would typically create a custom transformation or use a method designed for absolute positioning. A common approach is to use fig.dpi_scale_trans
which converts from points to display pixels, or to manually calculate positions based on fig.bbox
(the figure's bounding box in points).
Let's illustrate with an example of placing text at a specific point location on the figure.
import matplotlib.pyplot as plt
# Create a figure and an axes
fig, ax = plt.subplots(figsize=(6, 4)) # Figure size in inches
# Add some dummy data to the axes
ax.plot([0, 1], [0, 1])
ax.set_title('Example Plot')
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
# --- Positioning text using Figure Points ---
# Get the figure's bounding box in points
# fig.bbox is a Bbox object, its 'width' and 'height' are in points
fig_width_pts = fig.bbox.width
fig_height_pts = fig.bbox.height
# Define a position in points from the bottom-left corner
# For example, 50 points from left, 50 points from bottom
x_pt = 50
y_pt = 50
# To use fig.text(), we need to convert points to figure coordinates (0-1)
# This is often more practical than trying to directly use a 'points' transform
# for fig.text, which expects normalized coordinates by default.
# However, for true 'figure points' usage, you'd typically use a custom transform
# or a method that directly accepts points.
# A more direct way to place text using a transform that understands points:
# We can use the 'offset_copy' from 'transforms' to create a transform
# that shifts by a certain number of points from the figure's origin.
from matplotlib.transforms import Bbox, TransformedBbox, IdentityTransform
# Create a transform that is just the identity transform, then offset by points
# This is a bit advanced, but demonstrates the concept of working with transforms.
# For simpler cases, normalized figure coordinates are often sufficient.
# Let's place text at (x_pt, y_pt) using the figure's pixel transform
# This effectively places it in 'display' coordinates, which are derived from points.
# The 'transform' argument for text usually expects a transform from data/axes/figure coords.
# To place text directly in points, we can use the figure's transform to display coordinates
# and then specify the text position in those coordinates.
# A more straightforward approach for fixed-point positioning is to use `fig.text`
# with normalized figure coordinates and then adjust based on DPI if needed,
# or to use `fig.transFigure` to convert points to normalized figure coordinates.
# Example: Place text 50 points from the bottom-left using normalized figure coordinates
# by converting points to normalized figure coordinates.
normalized_x = x_pt / fig_width_pts
normalized_y = y_pt / fig_height_pts
fig.text(normalized_x, normalized_y, 'Text at 50,50 pts',
fontsize=10, color='red',
ha='left', va='bottom',
transform=fig.transFigure)
# Add another text at a different point location
x_pt_2 = fig_width_pts - 100 # 100 points from right edge
y_pt_2 = fig_height_pts - 50 # 50 points from top edge
normalized_x_2 = x_pt_2 / fig_width_pts
normalized_y_2 = y_pt_2 / fig_height_pts
fig.text(normalized_x_2, normalized_y_2, 'Text near top-right',
fontsize=10, color='blue',
ha='right', va='top',
transform=fig.transFigure)
plt.show()
fig.text()
expects normalized figure coordinates by default, you can convert your desired 'point' coordinates into normalized figure coordinates using the figure's total width and height in points (fig.bbox.width
, fig.bbox.height
). This allows you to effectively position elements using the 'figure points' concept.Common Pitfalls and Best Practices
Understanding when to use each coordinate system is crucial. Using figure points is ideal for elements that need to maintain a fixed physical size and position relative to the figure's edges, regardless of how the plot itself scales or changes. However, for elements that should scale with the data or the axes, data or axes coordinates are more appropriate.
- For plot data: Always use data coordinates.
- For annotations within an axes that scale with the axes: Use axes coordinates (
ax.text(x, y, ..., transform=ax.transAxes)
). - For annotations relative to the entire figure that scale with the figure: Use figure coordinates (
fig.text(x, y, ..., transform=fig.transFigure)
). - For elements with fixed physical size/position on the output: Convert desired point coordinates to normalized figure coordinates and use
fig.text
withtransform=fig.transFigure
, or explore advanced custom transforms if direct point-based methods are needed for other elements.