Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3ecb148

Browse filesBrowse files
authored
Merge pull request #27088 from rcomer/nearest-contour
Update `find_nearest_contour` and revert contour deprecations
2 parents 775fbc0 + e9a102f commit 3ecb148
Copy full SHA for 3ecb148

File tree

Expand file treeCollapse file tree

4 files changed

+45
-73
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+45
-73
lines changed
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Deprecations removed in ``contour``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
``contour.allsegs``, ``contour.allkinds``, and ``contour.find_nearest_contour`` are no
5+
longer marked for deprecation.

‎lib/matplotlib/contour.py

Copy file name to clipboardExpand all lines: lib/matplotlib/contour.py
+27-52Lines changed: 27 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Classes to support contour plotting and labelling for the Axes class.
33
"""
44

5+
from contextlib import ExitStack
56
import functools
67
import math
78
from numbers import Integral
@@ -937,12 +938,12 @@ def __init__(self, ax, *args,
937938
", ".join(map(repr, kwargs))
938939
)
939940

940-
allsegs = _api.deprecated("3.8", pending=True)(property(lambda self: [
941+
allsegs = property(lambda self: [
941942
[subp.vertices for subp in p._iter_connected_components()]
942-
for p in self.get_paths()]))
943-
allkinds = _api.deprecated("3.8", pending=True)(property(lambda self: [
943+
for p in self.get_paths()])
944+
allkinds = property(lambda self: [
944945
[subp.codes for subp in p._iter_connected_components()]
945-
for p in self.get_paths()]))
946+
for p in self.get_paths()])
946947
tcolors = _api.deprecated("3.8")(property(lambda self: [
947948
(tuple(rgba),) for rgba in self.to_rgba(self.cvalues, self.alpha)]))
948949
tlinewidths = _api.deprecated("3.8")(property(lambda self: [
@@ -1396,7 +1397,6 @@ def _find_nearest_contour(self, xy, indices=None):
13961397

13971398
return idx_level_min, idx_vtx_min, proj_min
13981399

1399-
@_api.deprecated("3.8")
14001400
def find_nearest_contour(self, x, y, indices=None, pixel=True):
14011401
"""
14021402
Find the point in the contour plot that is closest to ``(x, y)``.
@@ -1417,64 +1417,39 @@ def find_nearest_contour(self, x, y, indices=None, pixel=True):
14171417
14181418
Returns
14191419
-------
1420-
contour : `.Collection`
1421-
The contour that is closest to ``(x, y)``.
1422-
segment : int
1423-
The index of the `.Path` in *contour* that is closest to
1424-
``(x, y)``.
1420+
path : int
1421+
The index of the path that is closest to ``(x, y)``. Each path corresponds
1422+
to one contour level.
1423+
subpath : int
1424+
The index within that closest path of the subpath that is closest to
1425+
``(x, y)``. Each subpath corresponds to one unbroken contour line.
14251426
index : int
1426-
The index of the path segment in *segment* that is closest to
1427+
The index of the vertices within that subpath that are closest to
14271428
``(x, y)``.
14281429
xmin, ymin : float
14291430
The point in the contour plot that is closest to ``(x, y)``.
14301431
d2 : float
14311432
The squared distance from ``(xmin, ymin)`` to ``(x, y)``.
14321433
"""
1434+
segment = index = d2 = None
14331435

1434-
# This function uses a method that is probably quite
1435-
# inefficient based on converting each contour segment to
1436-
# pixel coordinates and then comparing the given point to
1437-
# those coordinates for each contour. This will probably be
1438-
# quite slow for complex contours, but for normal use it works
1439-
# sufficiently well that the time is not noticeable.
1440-
# Nonetheless, improvements could probably be made.
1436+
with ExitStack() as stack:
1437+
if not pixel:
1438+
# _find_nearest_contour works in pixel space. We want axes space, so
1439+
# effectively disable the transformation here by setting to identity.
1440+
stack.enter_context(self._cm_set(
1441+
transform=mtransforms.IdentityTransform()))
14411442

1442-
if self.filled:
1443-
raise ValueError("Method does not support filled contours.")
1443+
i_level, i_vtx, (xmin, ymin) = self._find_nearest_contour((x, y), indices)
14441444

1445-
if indices is None:
1446-
indices = range(len(self.collections))
1445+
if i_level is not None:
1446+
cc_cumlens = np.cumsum(
1447+
[*map(len, self._paths[i_level]._iter_connected_components())])
1448+
segment = cc_cumlens.searchsorted(i_vtx, "right")
1449+
index = i_vtx if segment == 0 else i_vtx - cc_cumlens[segment - 1]
1450+
d2 = (xmin-x)**2 + (ymin-y)**2
14471451

1448-
d2min = np.inf
1449-
conmin = None
1450-
segmin = None
1451-
imin = None
1452-
xmin = None
1453-
ymin = None
1454-
1455-
point = np.array([x, y])
1456-
1457-
for icon in indices:
1458-
con = self.collections[icon]
1459-
trans = con.get_transform()
1460-
paths = con.get_paths()
1461-
1462-
for segNum, linepath in enumerate(paths):
1463-
lc = linepath.vertices
1464-
# transfer all data points to screen coordinates if desired
1465-
if pixel:
1466-
lc = trans.transform(lc)
1467-
1468-
d2, xc, leg = _find_closest_point_on_path(lc, point)
1469-
if d2 < d2min:
1470-
d2min = d2
1471-
conmin = icon
1472-
segmin = segNum
1473-
imin = leg[1]
1474-
xmin = xc[0]
1475-
ymin = xc[1]
1476-
1477-
return (conmin, segmin, imin, xmin, ymin, d2min)
1452+
return (i_level, segment, index, xmin, ymin, d2)
14781453

14791454
def draw(self, renderer):
14801455
paths = self._paths

‎lib/matplotlib/contour.pyi

Copy file name to clipboardExpand all lines: lib/matplotlib/contour.pyi
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,6 @@ class ContourSet(ContourLabeler, Collection):
159159
) -> tuple[list[Artist], list[str]]: ...
160160
def find_nearest_contour(
161161
self, x: float, y: float, indices: Iterable[int] | None = ..., pixel: bool = ...
162-
) -> tuple[Collection, int, int, float, float, float]: ...
162+
) -> tuple[int, int, int, float, float, float]: ...
163163

164164
class QuadContourSet(ContourSet): ...

‎lib/matplotlib/tests/test_contour.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_contour.py
+12-20Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -569,23 +569,19 @@ def test_find_nearest_contour():
569569
img = np.exp(-np.pi * (np.sum((xy - 5)**2, 0)/5.**2))
570570
cs = plt.contour(img, 10)
571571

572-
with pytest.warns(mpl._api.MatplotlibDeprecationWarning):
573-
nearest_contour = cs.find_nearest_contour(1, 1, pixel=False)
572+
nearest_contour = cs.find_nearest_contour(1, 1, pixel=False)
574573
expected_nearest = (1, 0, 33, 1.965966, 1.965966, 1.866183)
575574
assert_array_almost_equal(nearest_contour, expected_nearest)
576575

577-
with pytest.warns(mpl._api.MatplotlibDeprecationWarning):
578-
nearest_contour = cs.find_nearest_contour(8, 1, pixel=False)
576+
nearest_contour = cs.find_nearest_contour(8, 1, pixel=False)
579577
expected_nearest = (1, 0, 5, 7.550173, 1.587542, 0.547550)
580578
assert_array_almost_equal(nearest_contour, expected_nearest)
581579

582-
with pytest.warns(mpl._api.MatplotlibDeprecationWarning):
583-
nearest_contour = cs.find_nearest_contour(2, 5, pixel=False)
580+
nearest_contour = cs.find_nearest_contour(2, 5, pixel=False)
584581
expected_nearest = (3, 0, 21, 1.884384, 5.023335, 0.013911)
585582
assert_array_almost_equal(nearest_contour, expected_nearest)
586583

587-
with pytest.warns(mpl._api.MatplotlibDeprecationWarning):
588-
nearest_contour = cs.find_nearest_contour(2, 5, indices=(5, 7), pixel=False)
584+
nearest_contour = cs.find_nearest_contour(2, 5, indices=(5, 7), pixel=False)
589585
expected_nearest = (5, 0, 16, 2.628202, 5.0, 0.394638)
590586
assert_array_almost_equal(nearest_contour, expected_nearest)
591587

@@ -595,16 +591,13 @@ def test_find_nearest_contour_no_filled():
595591
img = np.exp(-np.pi * (np.sum((xy - 5)**2, 0)/5.**2))
596592
cs = plt.contourf(img, 10)
597593

598-
with pytest.warns(mpl._api.MatplotlibDeprecationWarning), \
599-
pytest.raises(ValueError, match="Method does not support filled contours."):
594+
with pytest.raises(ValueError, match="Method does not support filled contours"):
600595
cs.find_nearest_contour(1, 1, pixel=False)
601596

602-
with pytest.warns(mpl._api.MatplotlibDeprecationWarning), \
603-
pytest.raises(ValueError, match="Method does not support filled contours."):
597+
with pytest.raises(ValueError, match="Method does not support filled contours"):
604598
cs.find_nearest_contour(1, 10, indices=(5, 7), pixel=False)
605599

606-
with pytest.warns(mpl._api.MatplotlibDeprecationWarning), \
607-
pytest.raises(ValueError, match="Method does not support filled contours."):
600+
with pytest.raises(ValueError, match="Method does not support filled contours"):
608601
cs.find_nearest_contour(2, 5, indices=(2, 7), pixel=True)
609602

610603

@@ -864,12 +857,11 @@ def test_allsegs_allkinds():
864857

865858
cs = plt.contour(x, y, z, levels=[0, 0.5])
866859

867-
# Expect two levels, first with 5 segments and the second with 4.
868-
with pytest.warns(PendingDeprecationWarning, match="all"):
869-
for result in [cs.allsegs, cs.allkinds]:
870-
assert len(result) == 2
871-
assert len(result[0]) == 5
872-
assert len(result[1]) == 4
860+
# Expect two levels, the first with 5 segments and the second with 4.
861+
for result in [cs.allsegs, cs.allkinds]:
862+
assert len(result) == 2
863+
assert len(result[0]) == 5
864+
assert len(result[1]) == 4
873865

874866

875867
def test_deprecated_apis():

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.