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

Skip to content

Commit 8f1141b

Browse files
committed
Make annotate/OffsetFrom unaffected by later mutation of coordinates.
The unpacking (`x, y = xy`) is safe wrt. units (we already perform the same unpacking later when actually computing coordinates) and prevents later mutation of the input array from affecting the artist (or the OffsetFrom instance), which is consistent with other artists. While at it, also inline OffsetFrom._get_scale, which is a one-liner.
1 parent 5140177 commit 8f1141b

File tree

2 files changed

+23
-15
lines changed

2 files changed

+23
-15
lines changed

lib/matplotlib/tests/test_text.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import matplotlib.transforms as mtransforms
1717
from matplotlib.testing.decorators import check_figures_equal, image_comparison
1818
from matplotlib.testing._markers import needs_usetex
19-
from matplotlib.text import Text, Annotation
19+
from matplotlib.text import Text, Annotation, OffsetFrom
2020

2121
pyparsing_version = parse_version(pyparsing.__version__)
2222

@@ -988,3 +988,19 @@ def test_text_math_antialiased_off_default_vs_manual(fig_test, fig_ref):
988988

989989
mpl.rcParams['text.antialiased'] = False
990990
fig_ref.text(0.5, 0.5, r"OutsideMath $I\'m \sqrt{2}$")
991+
992+
993+
@check_figures_equal(extensions=["png"])
994+
def test_annotate_and_offsetfrom_copy_input(fig_test, fig_ref):
995+
# Both approaches place the text (10, 0) pixels away from the center of the line.
996+
ax = fig_test.add_subplot()
997+
l, = ax.plot([0, 2], [0, 2])
998+
of_xy = np.array([.5, .5])
999+
ax.annotate("foo", textcoords=OffsetFrom(l, of_xy), xytext=(10, 0),
1000+
xy=(0, 0)) # xy is unused.
1001+
of_xy[:] = 1
1002+
ax = fig_ref.add_subplot()
1003+
l, = ax.plot([0, 2], [0, 2])
1004+
an_xy = np.array([.5, .5])
1005+
ax.annotate("foo", xy=an_xy, xycoords=l, xytext=(10, 0), textcoords="offset points")
1006+
an_xy[:] = 2

lib/matplotlib/text.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,7 +1389,8 @@ def __init__(self, artist, ref_coord, unit="points"):
13891389
The screen units to use (pixels or points) for the offset input.
13901390
"""
13911391
self._artist = artist
1392-
self._ref_coord = ref_coord
1392+
x, y = ref_coord # Make copy when ref_coord is an array (and check the shape).
1393+
self._ref_coord = x, y
13931394
self.set_unit(unit)
13941395

13951396
def set_unit(self, unit):
@@ -1407,13 +1408,6 @@ def get_unit(self):
14071408
"""Return the unit for input to the transform used by ``__call__``."""
14081409
return self._unit
14091410

1410-
def _get_scale(self, renderer):
1411-
unit = self.get_unit()
1412-
if unit == "pixels":
1413-
return 1.
1414-
else:
1415-
return renderer.points_to_pixels(1.)
1416-
14171411
def __call__(self, renderer):
14181412
"""
14191413
Return the offset transform.
@@ -1443,11 +1437,8 @@ def __call__(self, renderer):
14431437
x, y = self._artist.transform(self._ref_coord)
14441438
else:
14451439
_api.check_isinstance((Artist, BboxBase, Transform), artist=self._artist)
1446-
1447-
sc = self._get_scale(renderer)
1448-
tr = Affine2D().scale(sc).translate(x, y)
1449-
1450-
return tr
1440+
scale = 1 if self._unit == "pixels" else renderer.points_to_pixels(1)
1441+
return Affine2D().scale(scale).translate(x, y)
14511442

14521443

14531444
class _AnnotationBase:
@@ -1456,7 +1447,8 @@ def __init__(self,
14561447
xycoords='data',
14571448
annotation_clip=None):
14581449

1459-
self.xy = xy
1450+
x, y = xy # Make copy when xy is an array (and check the shape).
1451+
self.xy = x, y
14601452
self.xycoords = xycoords
14611453
self.set_annotation_clip(annotation_clip)
14621454

0 commit comments

Comments
 (0)