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='//')