Skip to content
Advertisement

Python highlight user chosen area in contourf plot

What is the best solution for highlighting an area in a contourf plot? I want the background to be opacity of 0.5 and the user chosen area to be normal. How can I achieve this?

Advertisement

Answer

In How to nicely plot clipped layered artists in matplotlib? Jake Vanderplas shows a way to draw a rectangle with a rectangular hole. The code can be adapted for your situation. The following example starts from a tutorial example, and highlights the third contour:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
from matplotlib.patches import PathPatch

def DoubleRect(xy1, width1, height1,
               xy2, width2, height2, **kwargs):
    base = np.array([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
    verts = np.vstack([xy1 + (width1, height1) * base,
                       xy2 + (width2, height2) * base[::-1],
                       xy1])
    codes = 2 * ([Path.MOVETO] + 4 * [Path.LINETO]) + [Path.CLOSEPOLY]
    return PathPatch(Path(verts, codes), **kwargs)

origin = 'lower'
delta = 0.025
x = y = np.arange(-3.0, 3.01, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X ** 2 - Y ** 2)
Z2 = np.exp(-(X - 1) ** 2 - (Y - 1) ** 2)
Z = (Z1 - Z2) * 2

fig, ax = plt.subplots()
contours = ax.contourf(X, Y, Z, 10, cmap=plt.cm.turbo, origin=origin)
# contours.collections[2].set_color('deepskyblue') # mark one contour

# calculate (or get) the coordinates of the hole
bbox = contours.collections[2].get_paths()[0].get_extents()
hole_xy, hole_width, hole_height = bbox.p0, bbox.width, bbox.height

# find the coordinates of the surrounding rectangle
xmin, xmax = ax.get_xlim()
ymin, ymax = ax.get_ylim()
full_rect = plt.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, color='black', alpha=0.5)
ax.add_patch(full_rect)

# create a rectangle with a hole to clip the surrounding rectangle
mask = DoubleRect((xmin, ymin), xmax - xmin, ymax - ymin,
                  hole_xy, hole_width, hole_height,
                  facecolor='none', edgecolor='none')
ax.add_patch(mask)
full_rect.set_clip_path(mask)

plt.show()

Instead of darkening the outside region, it could also be hatched (similar to the linked post). This would set the edge color of the mask to ‘black’, and create the full rectangle with hatching.

full_rect = plt.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, facecolor='none', edgecolor='black', hatch='//')

plt.contourf with one highlighted area

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement