Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 27cec21

Browse files
authored
Merge pull request #27212 from meeseeksmachine/auto-backport-of-pr-27088-on-v3.8.x
Backport PR #27088 on branch v3.8.x (Update `find_nearest_contour` and revert contour deprecations)
2 parents f3a1084 + ad92457 commit 27cec21

File tree

4 files changed

+45
-73
lines changed

4 files changed

+45
-73
lines changed
Lines 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

Lines 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
@@ -944,12 +945,12 @@ def __init__(self, ax, *args,
944945
", ".join(map(repr, kwargs))
945946
)
946947

947-
allsegs = _api.deprecated("3.8", pending=True)(property(lambda self: [
948+
allsegs = property(lambda self: [
948949
[subp.vertices for subp in p._iter_connected_components()]
949-
for p in self.get_paths()]))
950-
allkinds = _api.deprecated("3.8", pending=True)(property(lambda self: [
950+
for p in self.get_paths()])
951+
allkinds = property(lambda self: [
951952
[subp.codes for subp in p._iter_connected_components()]
952-
for p in self.get_paths()]))
953+
for p in self.get_paths()])
953954
tcolors = _api.deprecated("3.8")(property(lambda self: [
954955
(tuple(rgba),) for rgba in self.to_rgba(self.cvalues, self.alpha)]))
955956
tlinewidths = _api.deprecated("3.8")(property(lambda self: [
@@ -1403,7 +1404,6 @@ def _find_nearest_contour(self, xy, indices=None):
14031404

14041405
return idx_level_min, idx_vtx_min, proj_min
14051406

1406-
@_api.deprecated("3.8")
14071407
def find_nearest_contour(self, x, y, indices=None, pixel=True):
14081408
"""
14091409
Find the point in the contour plot that is closest to ``(x, y)``.
@@ -1424,64 +1424,39 @@ def find_nearest_contour(self, x, y, indices=None, pixel=True):
14241424
14251425
Returns
14261426
-------
1427-
contour : `.Collection`
1428-
The contour that is closest to ``(x, y)``.
1429-
segment : int
1430-
The index of the `.Path` in *contour* that is closest to
1431-
``(x, y)``.
1427+
path : int
1428+
The index of the path that is closest to ``(x, y)``. Each path corresponds
1429+
to one contour level.
1430+
subpath : int
1431+
The index within that closest path of the subpath that is closest to
1432+
``(x, y)``. Each subpath corresponds to one unbroken contour line.
14321433
index : int
1433-
The index of the path segment in *segment* that is closest to
1434+
The index of the vertices within that subpath that are closest to
14341435
``(x, y)``.
14351436
xmin, ymin : float
14361437
The point in the contour plot that is closest to ``(x, y)``.
14371438
d2 : float
14381439
The squared distance from ``(xmin, ymin)`` to ``(x, y)``.
14391440
"""
1441+
segment = index = d2 = None
14401442

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

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

1452-
if indices is None:
1453-
indices = range(len(self.collections))
1452+
if i_level is not None:
1453+
cc_cumlens = np.cumsum(
1454+
[*map(len, self._paths[i_level]._iter_connected_components())])
1455+
segment = cc_cumlens.searchsorted(i_vtx, "right")
1456+
index = i_vtx if segment == 0 else i_vtx - cc_cumlens[segment - 1]
1457+
d2 = (xmin-x)**2 + (ymin-y)**2
14541458

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

14861461
def draw(self, renderer):
14871462
paths = self._paths

lib/matplotlib/contour.pyi

Lines 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

Lines 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)