From e8ce73637972385ec95b6427e5d9aaaa42b2dfa4 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Tue, 22 Aug 2017 19:34:05 +0100 Subject: [PATCH 1/5] Use rectangle coords instead of width/height Fix up some incorrect bits in Rectangle Remember to update x1/y1 when setting x0/y0 Add methods to update x1/y1 --- lib/matplotlib/patches.py | 57 ++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index 7dd29757e35b..90b591d5a740 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -643,7 +643,7 @@ class Rectangle(Patch): """ def __str__(self): - pars = self._x, self._y, self._width, self._height, self.angle + pars = self._x0, self._y0, self._width, self._height, self.angle fmt = "Rectangle(xy=(%g, %g), width=%g, height=%g, angle=%g)" return fmt % pars @@ -662,10 +662,15 @@ def __init__(self, xy, width, height, angle=0.0, **kwargs): Patch.__init__(self, **kwargs) - self._x = xy[0] - self._y = xy[1] + self._x0 = xy[0] + self._y0 = xy[1] + self._width = width self._height = height + + self._x1 = self._x0 + self._width + self._y1 = self._y0 + self._height + self.angle = float(angle) # Note: This cannot be calculated until this is added to an Axes self._rect_transform = transforms.IdentityTransform() @@ -682,31 +687,37 @@ def _update_patch_transform(self): makes it very important to call the accessor method and not directly access the transformation member variable. """ - x = self.convert_xunits(self._x) - y = self.convert_yunits(self._y) - width = self.convert_xunits(self._width) - height = self.convert_yunits(self._height) - bbox = transforms.Bbox.from_bounds(x, y, width, height) + x0 = self.convert_xunits(self._x0) + y0 = self.convert_yunits(self._y0) + x1 = self.convert_xunits(self._x1) + y1 = self.convert_yunits(self._y1) + bbox = transforms.Bbox.from_extents(x0, y0, x1, y1) rot_trans = transforms.Affine2D() - rot_trans.rotate_deg_around(x, y, self.angle) + rot_trans.rotate_deg_around(x0, y0, self.angle) self._rect_transform = transforms.BboxTransformTo(bbox) self._rect_transform += rot_trans + def _update_x1(self): + self._x1 = self._x0 + self._width + + def _update_y1(self): + self._y1 = self._y0 + self._height + def get_patch_transform(self): self._update_patch_transform() return self._rect_transform def get_x(self): "Return the left coord of the rectangle" - return self._x + return self._x0 def get_y(self): "Return the bottom coord of the rectangle" - return self._y + return self._y0 def get_xy(self): "Return the left and bottom coords of the rectangle" - return self._x, self._y + return self._x0, self._y0 def get_width(self): "Return the width of the rectangle" @@ -722,7 +733,8 @@ def set_x(self, x): ACCEPTS: float """ - self._x = x + self._x0 = x + self._update_x1() self.stale = True def set_y(self, y): @@ -731,7 +743,8 @@ def set_y(self, y): ACCEPTS: float """ - self._y = y + self._y0 = y + self._update_y1() self.stale = True def set_xy(self, xy): @@ -740,7 +753,9 @@ def set_xy(self, xy): ACCEPTS: 2-item sequence """ - self._x, self._y = xy + self._x0, self._y0 = xy + self._update_x1() + self._update_y1() self.stale = True def set_width(self, w): @@ -750,6 +765,7 @@ def set_width(self, w): ACCEPTS: float """ self._width = w + self._update_x1() self.stale = True def set_height(self, h): @@ -759,6 +775,7 @@ def set_height(self, h): ACCEPTS: float """ self._height = h + self._update_y1() self.stale = True def set_bounds(self, *args): @@ -771,15 +788,17 @@ def set_bounds(self, *args): l, b, w, h = args[0] else: l, b, w, h = args - self._x = l - self._y = b + self._x0 = l + self._y0 = b self._width = w self._height = h + self._update_x1() + self._update_y1() self.stale = True def get_bbox(self): - return transforms.Bbox.from_bounds(self._x, self._y, - self._width, self._height) + return transforms.Bbox.from_extents(self._x0, self._y0, + self._x1, self._y1) xy = property(get_xy, set_xy) From 8208ddc9d88df4e0730a8ada99e815498a8712e3 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Tue, 22 Aug 2017 20:02:59 +0100 Subject: [PATCH 2/5] Add timedelta rectangle test --- lib/matplotlib/tests/test_patches.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index 7693148bef57..6fb53fc229b0 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -362,3 +362,15 @@ def test_connection_patch(): axesA=ax2, axesB=ax1, arrowstyle="->") ax2.add_artist(con) + + +def test_datetime_rectangle(): + # Check that creating a rectangle with timedeltas doesn't fail + from datetime import datetime, timedelta + + start = datetime(2017, 1, 1, 0, 0, 0) + delta = timedelta(seconds=16) + patch = mpatches.Rectangle((start, 0), delta, 1) + + fig, ax = plt.subplots() + ax.add_patch(patch) From 03fba6b4c784067636e59ac23a25fa4baaacafca Mon Sep 17 00:00:00 2001 From: Paul Ganssle Date: Tue, 22 Aug 2017 15:44:09 -0400 Subject: [PATCH 3/5] Add a test to ensure that datetimes cannot be used as deltas. --- lib/matplotlib/tests/test_patches.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index 6fb53fc229b0..2ea7af52e509 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -374,3 +374,16 @@ def test_datetime_rectangle(): fig, ax = plt.subplots() ax.add_patch(patch) + + +def test_datetime_datetime_fails(): + from datetime import datetime + + start = datetime(2017, 1, 1, 0, 0, 0) + dt_delta = datetime(1970, 1, 5) # Will be 5 days if units are done wrong + + with pytest.raises(TypeError): + mpatches.Rectangle((start, 0), dt_delta, 1) + + with pytest.raises(TypeError): + mpatches.Rectangle((0, start), 1, dt_delta) From f40607e20675560d1fe64e1e8f5c7038a4d2b325 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Fri, 25 Aug 2017 09:14:24 +0100 Subject: [PATCH 4/5] Convert units when returning Rect bbox --- lib/matplotlib/patches.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index 90b591d5a740..c9b48ef1f750 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -687,10 +687,7 @@ def _update_patch_transform(self): makes it very important to call the accessor method and not directly access the transformation member variable. """ - x0 = self.convert_xunits(self._x0) - y0 = self.convert_yunits(self._y0) - x1 = self.convert_xunits(self._x1) - y1 = self.convert_yunits(self._y1) + x0, y0, x1, y1 = self._convert_units() bbox = transforms.Bbox.from_extents(x0, y0, x1, y1) rot_trans = transforms.Affine2D() rot_trans.rotate_deg_around(x0, y0, self.angle) @@ -703,6 +700,16 @@ def _update_x1(self): def _update_y1(self): self._y1 = self._y0 + self._height + def _convert_units(self): + ''' + Convert bounds of the rectangle + ''' + x0 = self.convert_xunits(self._x0) + y0 = self.convert_yunits(self._y0) + x1 = self.convert_xunits(self._x1) + y1 = self.convert_yunits(self._y1) + return x0, y0, x1, y1 + def get_patch_transform(self): self._update_patch_transform() return self._rect_transform @@ -720,7 +727,7 @@ def get_xy(self): return self._x0, self._y0 def get_width(self): - "Return the width of the rectangle" + "Return the width of the rectangle" return self._width def get_height(self): @@ -797,6 +804,7 @@ def set_bounds(self, *args): self.stale = True def get_bbox(self): + x0, y0, x1, y1 = self._convert_units() return transforms.Bbox.from_extents(self._x0, self._y0, self._x1, self._y1) From 8ee4da2103a9726445ffcfbfac890dff9032a7b3 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Fri, 25 Aug 2017 09:20:05 +0100 Subject: [PATCH 5/5] Clean docstring of Rectangle methods --- lib/matplotlib/patches.py | 43 ++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index c9b48ef1f750..e42280f6e29c 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -650,12 +650,21 @@ def __str__(self): @docstring.dedent_interpd def __init__(self, xy, width, height, angle=0.0, **kwargs): """ + Parameters + ---------- + xy: length-2 tuple + The bottom and left rectangle coordinates + width: + Rectangle width + height: + Rectangle height + angle: float, optional + rotation in degrees anti-clockwise about *xy* (default is 0.0) + fill: bool, optional + Whether to fill the rectangle (default is ``True``) - *angle* - rotation in degrees (anti-clockwise) - - *fill* is a boolean indicating whether to fill the rectangle - + Notes + ----- Valid kwargs are: %(Patch)s """ @@ -735,21 +744,13 @@ def get_height(self): return self._height def set_x(self, x): - """ - Set the left coord of the rectangle - - ACCEPTS: float - """ + "Set the left coord of the rectangle" self._x0 = x self._update_x1() self.stale = True def set_y(self, y): - """ - Set the bottom coord of the rectangle - - ACCEPTS: float - """ + "Set the bottom coord of the rectangle" self._y0 = y self._update_y1() self.stale = True @@ -766,21 +767,13 @@ def set_xy(self, xy): self.stale = True def set_width(self, w): - """ - Set the width rectangle - - ACCEPTS: float - """ + "Set the width of the rectangle" self._width = w self._update_x1() self.stale = True def set_height(self, h): - """ - Set the width rectangle - - ACCEPTS: float - """ + "Set the height of the rectangle" self._height = h self._update_y1() self.stale = True pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy