Of course! The "edge" of a contourf plot in Matplotlib can be a bit ambiguous because contourf (filled contours) doesn't draw lines by default. The "edge" usually refers to one of two things:

- The lines between different colored regions (the "contour lines").
- The boundary of the entire filled area (the edge of the plot's data extent).
Let's break down how to control both of these.
Adding Lines Between Colored Regions (Contour Lines)
This is the most common interpretation. You want to see the boundaries where the color changes. The best way to do this is to overlay a standard contour plot on top of your contourf plot.
Method: Overlay contour on contourf
You create the filled contours first, then add the line contours on top. This ensures the lines are visible above the colors.
import numpy as np
import matplotlib.pyplot as plt
# 1. Create sample data
x = np.linspace(-3.0, 3.0, 100)
y = np.linspace(-3.0, 3.0, 100)
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X**2 + Y**2))
# 2. Create the plot
fig, ax = plt.subplots(figsize=(8, 6))
# First, create the filled contours
cf = ax.contourf(X, Y, Z, levels=20, cmap='viridis')
# Then, create the line contours and overlay them
# Use the same 'levels' to ensure lines match color boundaries
cs = ax.contour(X, Y, Z, levels=cf.levels, colors='k', linewidths=0.8)
# 3. Add labels to the contour lines
ax.clabel(cs, inline=True, fontsize=10)
# 4. Add colorbar and labels
fig.colorbar(cf, ax=ax, label='Function Value')
ax.set_title('Contourf with Overlaying Contour Lines')
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
ax.set_aspect('equal') # Ensure the plot is not distorted
plt.show()
Explanation:

ax.contourf(...): This creates the filled colored regions.ax.contour(...): This creates the line contours.levels=cf.levels: This is a key step. It tells the line contour function to use the exact same level boundaries as the filled contour. This ensures the lines perfectly match the edges of the colored regions.colors='k': Sets the line color to black ('k' is a common shorthand for black).linewidths=0.8: Sets the thickness of the contour lines.
ax.clabel(...): This is an optional but very useful function that adds numerical labels to the contour lines, showing the value ofZat that level.
Adding a Single Edge Around the Entire Area
Sometimes you want a single, thick line that defines the outermost boundary of your data. You can achieve this by finding the vertices of the outermost polygon and using plt.fill or plt.plot.
Method: Find and Plot the Outermost Polygon
This method is more manual but gives you precise control over the final edge.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import path
from scipy import ndimage # Used to find a single continuous path
# 1. Create sample data
x = np.linspace(-3.0, 3.0, 100)
y = np.linspace(-3.0, 3.0, 100)
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X**2 + Y**2))
# 2. Create the plot
fig, ax = plt.subplots(figsize=(8, 6))
# Create filled contours
cf = ax.contourf(X, Y, Z, levels=20, cmap='viridis')
# --- Method for finding the outermost edge ---
# Find a specific contour level (e.g., the 10th level from the list of levels)
# We'll use a low level to get a nice, closed shape.
contour_level = cf.levels[10]
# Or you can pick a specific value: contour_level = 0.2
# Get the collections of paths from the contour
collections = ax.contour(X, Y, Z, levels=[contour_level]).collections
if collections:
# The paths for our chosen level are in the first collection
paths = collections[0].get_paths()
if paths:
# We'll take the first path found. For a simple function like this,
# there's usually only one.
outer_path = paths[0]
# Get the vertices (x, y coordinates) of the path
vertices = outer_path.vertices
# Plot the edge using the vertices
ax.plot(vertices[:, 0], vertices[:, 1], color='red', linewidth=3, label='Outer Edge')
# 3. Add colorbar and labels
fig.colorbar(cf, ax=ax, label='Function Value')
ax.set_title('Contourf with a Custom Outer Edge')
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
ax.legend()
ax.set_aspect('equal')
plt.show()
Explanation:
- We create the
contourfplot as usual. - We then create a standard
contourplot, but this time we specify a single level usinglevels=[contour_level]. This isolates just the line for that specific value ofZ. ax.contour(...).collectionsreturns a list of "collections" (one for each level). We grab the first one..get_paths()extracts the geometric paths from that collection. For a simple peak, this will be a single closed loop..verticesgives us the(x, y)coordinates that make up that path.- Finally, we use
ax.plot()to draw a red line connecting these vertices, creating our custom edge.
Adding a "Hard" Edge with pcolormesh
If your goal is to have a sharp, pixelated edge instead of smooth, interpolated contours, pcolormesh is the right tool. It doesn't have "edges" between regions in the same way, but the entire grid has a distinct boundary.

import numpy as np
import matplotlib.pyplot as plt
# 1. Create sample data
x = np.linspace(-3.0, 3.0, 100)
y = np.linspace(-3.0, 3.0, 100)
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X**2 + Y**2))
# 2. Create the plot
fig, ax = plt.subplots(figsize=(8, 6))
# Use pcolormesh for a blocky, pixelated look
# The 'edgecolor' argument can add grid lines
pc = ax.pcolormesh(X, Y, Z, cmap='viridis', shading='auto', edgecolor='k', linewidths=0.1)
# 3. Add colorbar and labels
fig.colorbar(pc, ax=ax, label='Function Value')
ax.set_title('pcolormesh with Grid Lines')
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
ax.set_aspect('equal')
plt.show()
Explanation:
ax.pcolormesh(...): This creates a pseudocolor plot where each data point(Z[i,j])gets a color, and the result is a grid of colored rectangles.edgecolor='k',linewidths=0.1: This is what creates the "edge" effect. It draws thin black lines between the colored cells, giving it a grid-like appearance. This is different from the smooth contour lines ofcontourf.
Summary: Which Method to Use?
| Goal | Method | When to Use It |
|---|---|---|
| Show boundaries between color changes | Overlay contour on contourf |
The standard and most common way to visualize contour lines. |
| Draw a single outline | Find contour path and plot its vertices |
When you need a custom, thick border around a specific data level. |
| Create a grid-like, blocky plot | Use pcolormesh with edgecolor |
When your data is naturally gridded and you want to avoid interpolation artifacts. |
