Thursday, March 30, 2017

set_clip_path on a matplotlib clabel not clipping properly

Leave a Comment

I'm making a contour plot that is clipped to a polygon path:

import matplotlib.pyplot as plt from matplotlib.patches import Polygon import numpy as np  fig = plt.figure() axes = plt.subplot() x,y = np.meshgrid( np.linspace(-10,10,51), np.linspace(-10,10,51) )  z = np.sin(np.sqrt(x**2+y**2)) CS =  axes.contour(x, y, z, np.linspace(-1,1,11) ) axes.set_aspect('equal')  # clip contours by polygon radius = 8 t = np.linspace(0,2*np.pi,101) x_bound,y_bound = radius*np.sin(t),radius*(np.cos(t)+0.1*(np.cos(7*t))) clip_map = Polygon(list(zip(x_bound,y_bound)),fc='#EEEEEE',ec='none') axes.add_patch(clip_map) for collection in CS.collections:     collection.set_clip_path(clip_map)  # label the contours     CLB = axes.clabel(CS, colors='black') for text_object in CLB:     text_object.set_clip_path(clip_map) # Doesn't do anything!  plt.show() 

To my surprise, the labels aren't clipped despite the Text objects having a set_clip_path method that doesn't return an error:

contour plot where labels aren't clipped

How can I clip the labels outside of the gray polygon area? Do I need to resort to manually finding the X and Y positions, calculating point in polygon, and set_visible = False for each Text item? Why doesn't this code work as-is? I'm using matplotlib version 1.5.1 and python 3.5.1.

1 Answers

Answers 1

Just in case someone comes across the same issue someday, here's a solution that resorts to having to use the shapely package to test for point in polygon to set the visibility state of the Text object. It gets the job done, but it would be nice if it was possible to use set_clip_path to work directly on the Text object.

import matplotlib.pyplot as plt from matplotlib.patches import Polygon import numpy as np from shapely.geometry import Polygon as ShapelyPolygon from shapely.geometry import Point as ShapelyPoint  fig = plt.figure() axes = plt.subplot() x,y = np.meshgrid( np.linspace(-10,10,51), np.linspace(-10,10,51) )  z = np.sin(np.sqrt(x**2+y**2)) CS =  axes.contour(x, y, z, np.linspace(-1,1,11) ) axes.set_aspect('equal')  # clip contours by polygon radius = 8 t = np.linspace(0,2*np.pi,101) x_bound,y_bound = radius*np.sin(t),radius*(np.cos(t)+0.1*(np.cos(7*t))) clip_map = Polygon(list(zip(x_bound,y_bound)),fc='#EEEEEE',ec='none') axes.add_patch(clip_map) for collection in CS.collections:     collection.set_clip_path(clip_map)  # label the contours     CLB = axes.clabel(CS, colors='black') clip_map_shapely = ShapelyPolygon(clip_map.get_xy())  for text_object in CLB:     if not clip_map_shapely.contains(ShapelyPoint(text_object.get_position())):         text_object.set_visible(False)  plt.show() 

enter image description here

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment