find_nearest_contour is deprecated. Now what?

130 Views Asked by At

I'm using Matplotlib contours to explore a 2d map. I'm using contour.find_nearest_contour to get the range of x and y of the contour that passes close to a point x0, y0, as follows:

cs = fig.gca().contour(x, y, image, [level])

cont, seg, idx, xm, ym, d2 = cs.find_nearest_contour(x0, y0, pixel=False)

min_x = cs.allsegs[cont][seg][:, 0].min()
max_x = cs.allsegs[cont][seg][:, 0].max()
min_y = cs.allsegs[cont][seg][:, 1].min()
max_y = cs.allsegs[cont][seg][:, 1].max()

cont, seg, idx, xm, ym, d2 = cs.find_nearest_contour(x0, y0, pixel=False)

Now Matplotlib v3.8 is throwing a MatplotlibDeprecationWarning, but I can't find any document that explains how to get the same functionality.

Note that a given contour level can create multiple segments, and I also need what segment is closer to my point. I need seg in my line of code, practically. This is not shared from the private method _find_nearest_contour which was a very good candidate for replacement.

1

There are 1 best solutions below

2
Trenton McKinney On
  • Continue using .find_nearest_contour until it's removed.
  • Based on this comment in matplotlib issue 27070, the private method, ._find_nearest_contour, can be used until, or if, a public method is reimplemented.
    • It was deprecated because the old return value, ..., doesn't really make much sense for the new internal representation of ContourSets (there's a single Collection, and a single path per level)

    • If you have existing code, you will probably need to do one of the following:
      • Continue using matplotlib less then 3.8
      • Use the newest implementation and update your code with respect to the new Returns
  • Given the sample code:
    • CS.find_nearest_contour(0, 0)(5, 0, 296, 209.70308429471964, 168.30113207547168, 72300.65462060366)
    • CS._find_nearest_contour((0, 0))(5, 296, array([209.70308429, 168.30113208]))
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

# Basic contour plot
fig, ax = plt.subplots(figsize=(7, 7))
CS = ax.contour(X, Y, Z)

CS._find_nearest_contour((0, 0))  # private method

enter image description here

Signature: CS._find_nearest_contour(xy, indices=None)
Docstring:
Find the point in the unfilled contour plot that is closest (in screen
space) to point *xy*.

Parameters
----------
xy : tuple[float, float]
    The reference point (in screen space).
indices : list of int or None, default: None
    Indices of contour levels to consider.  If None (the default), all levels
    are considered.

Returns
-------
idx_level_min : int
    The index of the contour level closest to *xy*.
idx_vtx_min : int
    The index of the `.Path` segment closest to *xy* (at that level).
proj : (float, float)
    The point in the contour plot closest to *xy*.
File:      c:\users\trenton\anaconda3\envs\py312\lib\site-packages\matplotlib\contour.py
Type:      method

Regarding Private Methods