Drawing Shapes (Patches)
Patches are filled geometric shapes — rectangles, circles, polygons, and arrows — that you place directly on an axes to highlight regions, draw diagrams, or annotate your data with custom graphics.
Learn Drawing Shapes (Patches) in our free Matplotlib course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Matplotlib course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll add shapes with ax.add_patch() , control fill and outline with facecolor / edgecolor / alpha , draw arrows, and batch many shapes with a PatchCollection .
Patches live in the matplotlib.patches module. Build a shape, then call ax.add_patch() to place it. A Rectangle takes its bottom-left corner plus a width and height; a Circle takes a center and a radius. Patches do not auto-scale the view, so set the limits yourself.
What you'll see: a sky-blue rectangle with a navy outline on the left and a salmon circle with a dark-red outline on the right, both correctly proportioned because the aspect ratio is locked.
A Polygon takes an array of corner points, and a FancyArrow draws an arrow from a base point along a direction. A translucent Rectangle behind your data (low alpha ) is a clean way to shade a region of interest without hiding the line.
Calling add_patch hundreds of times is slow. A PatchCollection bundles a list of shapes into one artist you add with ax.add_collection() , and you can color them all at once — even map a data array through a colormap.
What you'll see: forty translucent circles scattered across the plot, each tinted along a viridis colormap by its radius, with a colorbar showing how size maps to color — all drawn in one efficient collection.
Replace each ___ to draw a green square on the axes.
Patches do not expand the view. ✅ Set ax.set_xlim() / set_ylim() (or call ax.autoscale_view() ) so the shape is inside the visible area.
The axes have unequal unit sizes. ✅ Call ax.set_aspect('equal') .
add_patch takes one patch. ✅ For many shapes, wrap them in PatchCollection and use ax.add_collection() .
Use a Rectangle for the housing and three Circles for the lights to draw a traffic light.
Lesson complete — you can draw on your plots!
You added rectangles, circles, polygons, and arrows, controlled fill and outline with facecolor, edgecolor, and alpha, shaded a region, and batched many shapes with a PatchCollection.
🚀 Up next: Interactive Event Handling — respond to clicks, key presses, and mouse motion in a live figure window.
Practice quiz
What is a patch in Matplotlib?
- A bug fix
- A filled 2-D shape like Rectangle or Circle
- A type of colormap
- A legend entry
Answer: A filled 2-D shape like Rectangle or Circle. A patch is a filled geometric shape from matplotlib.patches, such as Rectangle or Circle.
Which call places a single shape onto an axes?
- ax.draw_shape()
- ax.patch()
- ax.shape()
- ax.add_patch()
Answer: ax.add_patch(). ax.add_patch(shape) adds one patch to the axes.
What arguments does Rectangle take?
- Its bottom-left corner plus a width and height
- Two opposite corners
- A center and radius
- Four separate corner points
Answer: Its bottom-left corner plus a width and height. Rectangle((x, y), width, height) is defined by its bottom-left corner, width, and height.
What arguments does Circle take?
- Three points on the circle
- A bounding box
- A center and a radius
- A start and end angle
Answer: A center and a radius. Circle((cx, cy), r) is defined by its center and radius.
Why might a shape not appear after add_patch?
- The color was wrong
- Patches do not auto-scale the view, so set the limits
- You must call it twice
- Patches need a legend
Answer: Patches do not auto-scale the view, so set the limits. Patches do not expand the view; set ax.set_xlim()/set_ylim() so the shape is visible.
Why does a Circle sometimes look like an oval?
- The radius is negative
- alpha is too low
- The figure is too small
- The axes have unequal unit sizes
Answer: The axes have unequal unit sizes. Different pixel sizes per data unit squash a circle; ax.set_aspect('equal') fixes it.
What does facecolor control?
- The interior fill of the shape
- The axis labels
- The outline only
- The shadow
Answer: The interior fill of the shape. facecolor fills the interior, while edgecolor draws the outline.
How do you make a shape hollow so only its outline shows?
- alpha=0
- Set fill=None and no edge
- facecolor='none'
- Remove the patch
Answer: facecolor='none'. facecolor='none' leaves the interior empty so only the edge shows.
How do you draw many shapes efficiently and color them together?
- Call add_patch in a loop only
- Use plt.scatter
- Plot each as a line
- Wrap them in a PatchCollection and add_collection()
Answer: Wrap them in a PatchCollection and add_collection(). A PatchCollection bundles many shapes into one artist added with ax.add_collection().
What does set_aspect('equal') ensure?
- The figure is square inches
- One data unit takes the same pixels on both axes
- The axes are logarithmic
- The patch is filled
Answer: One data unit takes the same pixels on both axes. set_aspect('equal') makes one data unit equal pixels on both axes, so circles look round.