I would like to control the location of matplotlib clabels on a contour plot, but without utilizing the manual=True flag in clabel. For example, I would like to specify an x-coordinate, and have labels created at the points that pass through this line. I see that you can get the location of the individual labels using get_position(), but I am stuck at that. Any help would be greatly appreciated. Thanks!
2 Answers
Yes, there now is a way to control label locations! https://github.com/matplotlib/matplotlib/pull/642
plt.figure()
CS = plt.contour(X, Y, Z)
manual_locations = [(-1, -1.4), (-0.62, -0.7), (-2, 0.5), (1.7, 1.2), (2.0, 1.4), (2.4, 1.7)]
plt.clabel(CS, inline=1, fontsize=10, manual=manual_locations)

- 18,278
- 20
- 86
- 118
-
1manual can be an iterable object of x,y tuples. Contour labels will be created as if mouse is clicked at each x,y positions. – Faber Dec 02 '14 at 21:40
-
3Is there a way to allow automated labelling, and then loop through the labels to remove (and maybe improve) any that intersect the axes? – alphabetasoup Feb 24 '16 at 21:13
-
1The labels with be placed on a contour **near** the locations given by `manual`. – Walter Jun 26 '18 at 16:08
-
I like the answer even though this isn't strictly what was requested. The manual locations can be copied and modified from the automatically generated output without too much trouble. – nedlrichards May 30 '22 at 16:07
No, there is no way built into matplotlib to do that. You are supposed to either live with the default locations or go fully interactive with manual and using the mouse.
You might want to file this as a bug report upstream so they can improve their algorithms.
There are multiple options to work around this. The first one is to programmatically place text on the contour figure. You will not be able to reliably remove the lines underneath the text this way. Assuming you have a contour c
you can find the contour lines in c.collections
. For every contour line invoke get_paths
and place your text on that path.
The other option would be to replace the code for manual placement (in matplotlib.contour.BlockingContourLabeler
) or tweak the code that finds the label positions (in matplotlib.contour.locate_label
), but both functions are pretty dense. If you can come up with a working replacement for locate_label
just overwrite the old method in your plotting macro
def your_locate_label(self, linecontour, labelwidth):
# some magic
pass
ar = np.array([[1,0], [0,1]]
c = matplotlib.contour(ar)
c.locate_label = your_locate_label
c.clabel()
Btw, if you use ipython
you can easily view the function source from your interactive session with
%psource c.clabel
or directly invoke your $EDITOR
on the file were it is defined with
%edit c.clabel

- 55,163
- 11
- 60
- 80
-
1I didn't find this issue posted, so I made a new one: https://github.com/matplotlib/matplotlib/issues/613 – keflavich Dec 07 '11 at 18:42