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:
JavaScript
x
45
45
1
import numpy as np
2
import matplotlib.pyplot as plt
3
from matplotlib.path import Path
4
from matplotlib.patches import PathPatch
5
6
def DoubleRect(xy1, width1, height1,
7
xy2, width2, height2, **kwargs):
8
base = np.array([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
9
verts = np.vstack([xy1 + (width1, height1) * base,
10
xy2 + (width2, height2) * base[::-1],
11
xy1])
12
codes = 2 * ([Path.MOVETO] + 4 * [Path.LINETO]) + [Path.CLOSEPOLY]
13
return PathPatch(Path(verts, codes), **kwargs)
14
15
origin = 'lower'
16
delta = 0.025
17
x = y = np.arange(-3.0, 3.01, delta)
18
X, Y = np.meshgrid(x, y)
19
Z1 = np.exp(-X ** 2 - Y ** 2)
20
Z2 = np.exp(-(X - 1) ** 2 - (Y - 1) ** 2)
21
Z = (Z1 - Z2) * 2
22
23
fig, ax = plt.subplots()
24
contours = ax.contourf(X, Y, Z, 10, cmap=plt.cm.turbo, origin=origin)
25
# contours.collections[2].set_color('deepskyblue') # mark one contour
26
27
# calculate (or get) the coordinates of the hole
28
bbox = contours.collections[2].get_paths()[0].get_extents()
29
hole_xy, hole_width, hole_height = bbox.p0, bbox.width, bbox.height
30
31
# find the coordinates of the surrounding rectangle
32
xmin, xmax = ax.get_xlim()
33
ymin, ymax = ax.get_ylim()
34
full_rect = plt.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, color='black', alpha=0.5)
35
ax.add_patch(full_rect)
36
37
# create a rectangle with a hole to clip the surrounding rectangle
38
mask = DoubleRect((xmin, ymin), xmax - xmin, ymax - ymin,
39
hole_xy, hole_width, hole_height,
40
facecolor='none', edgecolor='none')
41
ax.add_patch(mask)
42
full_rect.set_clip_path(mask)
43
44
plt.show()
45
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.
JavaScript
1
2
1
full_rect = plt.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, facecolor='none', edgecolor='black', hatch='//')
2