1

How can I retrieve the automatically determined contour label coordinates in the example below?

matplotlib example from the documentation

import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.pyplot as plt


delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, 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()
CS = ax.contour(X, Y, Z)
CS_labels = ax.clabel(CS, inline=True, fontsize=10)
ax.set_title('Simplest default with labels')

enter image description here

I would like to do something like

label_locations = CS_labels.get_label_coords()

So that I can start with an auto-selected set and modify manually as needed. This would be especially helpful when dealing with labels in geospatial coordinates.

Update:
The solution provided by swatchai works for both matplotlib and cartopy.

for txobj in CS.labelTexts:
    pos = txobj.get_position()
    txt = txobj.get_text()
    print(pos, txt)

Label positions are best retrieved from the CS object, instead of the CS_labels object.

Note:
tdy's solution only works for matplotlib, but not when using cartopy GeoAxes, as ax.clabel() returns 'NoneType' for CS_labels so CS_labels[0].get_position() cannot be accessed that way.

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
  • Related matplotlib question: https://stackoverflow.com/questions/19418901/get-coordinates-from-the-contour-in-matplotlib Helpful, but unrelated, cartopy contour question: https://stackoverflow.com/questions/61032307/matplotlib-cartopy-solid-fill-underneath-contour-plot – friedrichknuth Mar 25 '21 at 21:49

1 Answers1

1

For cartopy, once you created contour labels, you can get access to the labels by

CS.labelTexts  #CS is contour_collection set

Here is the runnable code that demonstrates all the steps.

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy
import numpy as np

delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 3.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)*20
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)*20
Z = (Z1 - Z2) * 2

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())

CS = ax.contour(X, Y, Z)

ax.clabel(
    CS,
    colors=['black'],
    manual=False,
    inline=True,
    fmt=' {:.0f} '.format
)

ax.set_extent([-3,3,-2,3])
ax.gridlines(draw_labels=True)
plt.show()

contourplot

To list the contour label texts:-

CS.labelTexts

Output:

[Text(1.003030188944607, 0.7749999999999897, ' -30 '),
 Text(1.4249999999999843, 1.7059169688922102, ' -20 '),
 Text(0.30880609807150927, 0.9499999999999895, ' -10 '),
 Text(0.6000000000000081, 0.3999999999999915, ' 0 '),
 Text(-0.7000000000000091, -0.9440944811557408, ' 10 '),
 Text(-0.12500000000001066, -0.8102372655970758, ' 20 '),
 Text(-0.050000000000010925, 0.24709487906649752, ' 30 ')]

To print position and text of each label:-

for txobj in CS.labelTexts:
    pos = txobj.get_position()
    txt = txobj.get_text()
    print(pos, txt)

The output:

(1.003030188944607, 0.7749999999999897)  -30 
(1.4249999999999843, 1.7059169688922102)  -20 
(0.30880609807150927, 0.9499999999999895)  -10 
(0.6000000000000081, 0.3999999999999915)  0 
(-0.7000000000000091, -0.9440944811557408)  10 
(-0.12500000000001066, -0.8102372655970758)  20 
(-0.050000000000010925, 0.24709487906649752)  30 

If you want to manipulate each of the labels, the methods .set_text() and .set_position() are often used.

swatchai
  • 17,400
  • 3
  • 39
  • 58