Search code examples
pythonmatplotliblabelcontour

contour clabel custom text


I'm plotting hyperbolas in their general form

cntr = ax.contour(x, y, (A * x ** 2 + B * x * y + C * y ** 2 + D * x + E * y - 1), [0])

and I'd like to draw their names on the contour, for example, from 0 to N-1. How to do this?

There is a function

ax.clabel(cntr, fmt="%2.1f", use_clabeltext=True)

but it does not allow passing custom text.

Below is my drawing of what I'd like to achieve. The position of custom labels can be any although ideally, I'd like to be them as in the clabel function.

enter image description here


Update 1.

A hacky way would be to shift each contour level by its index and enumerate them:

cntr = ax.contour(x, y, (A * x ** 2 + B * x * y + C * y ** 2 + D * x + E * y - 1 + idx), [idx])

This approach wouldn't work for custom text though.


Solution

  • ax.clabel will return a list of text objects that you can modify with the set method:

    import matplotlib.pyplot as plt
    import numpy as np
    
    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)
    
    txt_objects = ax.clabel(CS, fmt="%2.1f", use_clabeltext=True)
    
    new_labels = range(len(txt_objects))
    for t, l in zip(txt_objects, new_labels):
        t.set(text=l)
    
    plt.show()
    

    Output:

    enter image description here