Skip to content

Commit 41d7e12

Browse files
committed
Scale margins to data, plus padding, by default
Fix #4891
1 parent b698502 commit 41d7e12

File tree

11 files changed

+310
-127
lines changed

11 files changed

+310
-127
lines changed

lib/matplotlib/artist.py

+85
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ def __init__(self):
118118
self._sketch = rcParams['path.sketch']
119119
self._path_effects = rcParams['path.effects']
120120

121+
self._margins = {}
122+
121123
def __getstate__(self):
122124
d = self.__dict__.copy()
123125
# remove the unpicklable remove method, this will get re-added on load
@@ -898,6 +900,89 @@ def set_zorder(self, level):
898900
self.pchanged()
899901
self.stale = True
900902

903+
def get_top_margin(self):
904+
"""
905+
Get whether a margin should be applied to the top of the Artist.
906+
"""
907+
return self._margins.get('top', True)
908+
909+
def set_top_margin(self, margin):
910+
"""
911+
Set whether a margin should be applied to the top of the Artist.
912+
"""
913+
if margin != self._margins.get('top', True):
914+
self.stale = True
915+
self._margins['top'] = margin
916+
917+
def get_bottom_margin(self):
918+
"""
919+
Get whether a margin should be applied to the bottom of the Artist.
920+
"""
921+
return self._margins.get('bottom', True)
922+
923+
def set_bottom_margin(self, margin):
924+
"""
925+
Set whether a margin should be applied to the bottom of the Artist.
926+
"""
927+
if margin != self._margins.get('bottom', True):
928+
self.stale = True
929+
self._margins['bottom'] = margin
930+
931+
def get_left_margin(self):
932+
"""
933+
Get whether a margin should be applied to the left of the Artist.
934+
"""
935+
return self._margins.get('left', True)
936+
937+
def set_left_margin(self, margin):
938+
"""
939+
Set whether a margin should be applied to the left of the Artist.
940+
"""
941+
if margin != self._margins.get('left', True):
942+
self.stale = True
943+
self._margins['left'] = margin
944+
945+
def get_right_margin(self):
946+
"""
947+
Get whether a margin should be applied to the right of the Artist.
948+
"""
949+
return self._margins.get('right', True)
950+
951+
def set_right_margin(self, margin):
952+
"""
953+
Set whether a margin should be applied to the right of the Artist.
954+
"""
955+
if margin != self._margins.get('right', True):
956+
self.stale = True
957+
self._margins['right'] = margin
958+
959+
def get_margins(self):
960+
"""
961+
Returns a dictionary describing whether a margin should be applied on
962+
each of the sides (top, bottom, left and right).
963+
"""
964+
return self._margins
965+
966+
def set_margins(self, margins):
967+
"""
968+
Set the dictionary describing whether a margin should be applied on
969+
each of the sides (top, bottom, left and right). Missing keys are
970+
assumed to be `True`. If `True` or `False` are passed in, all
971+
sides are set to that value.
972+
"""
973+
if margins in (True, False):
974+
margins = {
975+
'top': margins,
976+
'bottom': margins,
977+
'left': margins,
978+
'right': margins
979+
}
980+
981+
if margins != self._margins:
982+
self.stale = True
983+
984+
self._margins = margins
985+
901986
def update_from(self, other):
902987
'Copy properties from *other* to *self*.'
903988
self._transform = other._transform

lib/matplotlib/axes/_axes.py

+33-14
Original file line numberDiff line numberDiff line change
@@ -2104,16 +2104,21 @@ def make_iterable(x):
21042104
if yerr is not None:
21052105
yerr = self.convert_yunits(yerr)
21062106

2107-
if align == 'edge':
2108-
pass
2109-
elif align == 'center':
2107+
margins = {}
2108+
2109+
if orientation == 'vertical':
2110+
margins = {'bottom': False}
2111+
elif orientation == 'horizontal':
2112+
margins = {'left': False}
2113+
2114+
if align == 'center':
21102115
if orientation == 'vertical':
21112116
left = [left[i] - width[i] / 2. for i in xrange(len(left))]
21122117
elif orientation == 'horizontal':
21132118
bottom = [bottom[i] - height[i] / 2.
21142119
for i in xrange(len(bottom))]
21152120

2116-
else:
2121+
elif align != 'edge':
21172122
raise ValueError('invalid alignment: %s' % align)
21182123

21192124
args = zip(left, bottom, width, height, color, edgecolor, linewidth)
@@ -2129,7 +2134,8 @@ def make_iterable(x):
21292134
facecolor=c,
21302135
edgecolor=e,
21312136
linewidth=lw,
2132-
label='_nolegend_'
2137+
label='_nolegend_',
2138+
margins=margins
21332139
)
21342140
r.update(kwargs)
21352141
r.get_path()._interpolation_steps = 100
@@ -5267,7 +5273,7 @@ def pcolor(self, *args, **kwargs):
52675273

52685274
kwargs.setdefault('snap', False)
52695275

5270-
collection = mcoll.PolyCollection(verts, **kwargs)
5276+
collection = mcoll.PolyCollection(verts, margins=False, **kwargs)
52715277

52725278
collection.set_alpha(alpha)
52735279
collection.set_array(C)
@@ -5302,9 +5308,9 @@ def pcolor(self, *args, **kwargs):
53025308
maxy = np.amax(y)
53035309

53045310
corners = (minx, miny), (maxx, maxy)
5311+
self.add_collection(collection, autolim=False)
53055312
self.update_datalim(corners)
53065313
self.autoscale_view()
5307-
self.add_collection(collection, autolim=False)
53085314
return collection
53095315

53105316
@unpack_labeled_data(label_namer=None)
@@ -5419,7 +5425,8 @@ def pcolormesh(self, *args, **kwargs):
54195425

54205426
collection = mcoll.QuadMesh(
54215427
Nx - 1, Ny - 1, coords,
5422-
antialiased=antialiased, shading=shading, **kwargs)
5428+
antialiased=antialiased, shading=shading, margins=False,
5429+
**kwargs)
54235430
collection.set_alpha(alpha)
54245431
collection.set_array(C)
54255432
if norm is not None and not isinstance(norm, mcolors.Normalize):
@@ -5451,9 +5458,9 @@ def pcolormesh(self, *args, **kwargs):
54515458
maxy = np.amax(Y)
54525459

54535460
corners = (minx, miny), (maxx, maxy)
5461+
self.add_collection(collection, autolim=False)
54545462
self.update_datalim(corners)
54555463
self.autoscale_view()
5456-
self.add_collection(collection, autolim=False)
54575464
return collection
54585465

54595466
@unpack_labeled_data(label_namer=None)
@@ -5603,7 +5610,8 @@ def pcolorfast(self, *args, **kwargs):
56035610
# The QuadMesh class can also be changed to
56045611
# handle relevant superclass kwargs; the initializer
56055612
# should do much more than it does now.
5606-
collection = mcoll.QuadMesh(nc, nr, coords, 0, edgecolors="None")
5613+
collection = mcoll.QuadMesh(nc, nr, coords, 0, edgecolors="None",
5614+
margins=False)
56075615
collection.set_alpha(alpha)
56085616
collection.set_array(C)
56095617
collection.set_cmap(cmap)
@@ -5649,15 +5657,19 @@ def contour(self, *args, **kwargs):
56495657
if not self._hold:
56505658
self.cla()
56515659
kwargs['filled'] = False
5652-
return mcontour.QuadContourSet(self, *args, **kwargs)
5660+
contours = mcontour.QuadContourSet(self, *args, **kwargs)
5661+
self.autoscale_view()
5662+
return contours
56535663
contour.__doc__ = mcontour.QuadContourSet.contour_doc
56545664

56555665
@unpack_labeled_data()
56565666
def contourf(self, *args, **kwargs):
56575667
if not self._hold:
56585668
self.cla()
56595669
kwargs['filled'] = True
5660-
return mcontour.QuadContourSet(self, *args, **kwargs)
5670+
contours = mcontour.QuadContourSet(self, *args, **kwargs)
5671+
self.autoscale_view()
5672+
return contours
56615673
contourf.__doc__ = mcontour.QuadContourSet.contour_doc
56625674

56635675
def clabel(self, CS, *args, **kwargs):
@@ -6037,6 +6049,11 @@ def hist(self, x, bins=None, range=None, normed=False, weights=None,
60376049
else:
60386050
n = [m[slc].cumsum()[slc] for m in n]
60396051

6052+
if orientation == 'horizontal':
6053+
margins = {'left': False}
6054+
else:
6055+
margins = {'bottom': False}
6056+
60406057
patches = []
60416058

60426059
if histtype.startswith('bar'):
@@ -6177,14 +6194,16 @@ def hist(self, x, bins=None, range=None, normed=False, weights=None,
61776194
patches.append(self.fill(
61786195
x, y,
61796196
closed=True,
6180-
facecolor=c))
6197+
facecolor=c,
6198+
margins=margins))
61816199
else:
61826200
for x, y, c in reversed(list(zip(xvals, yvals, color))):
61836201
split = 2 * len(bins)
61846202
patches.append(self.fill(
61856203
x[:split], y[:split],
61866204
closed=False, edgecolor=c,
6187-
fill=False))
6205+
fill=False,
6206+
margins=margins))
61886207

61896208
# we return patches, so put it back in the expected order
61906209
patches.reverse()

0 commit comments

Comments
 (0)