Skip to content

Commit c1ea241

Browse files
committed
Make logscale bar/hist autolimits more consistents.
The bottom limit of log-scaled bar/hist plots now defaults to applying normal margins (possibly with null limits expansion) to the data limits, rather than being hardcoded to 1/log_base. See changelog. Delete two tests that asserted that the lower limit was at 1/log_base.
1 parent f2116d8 commit c1ea241

File tree

7 files changed

+29
-3634
lines changed

7 files changed

+29
-3634
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
log-scale bar() / hist() autolimits change
2+
``````````````````````````````````````````
3+
4+
The autolimits computation in `~.Axes.bar` and `~.Axes.hist` when the axes
5+
already uses log-scale has changed to match the computation when the axes is
6+
switched to log-scale after the call to `~.Axes.bar` and `~.Axes.hist`, and
7+
when calling ``bar(..., log=True)`` / ``hist(..., log=True)``: if there are
8+
at least two different bar heights, add the normal axes margins to them (in
9+
log-scale); if there is only a single bar height, expand the axes limits by one
10+
order of magnitude around it and then apply axes margins.

lib/matplotlib/axes/_axes.py

Lines changed: 3 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,20 +2303,12 @@ def bar(self, x, height, width=0.8, bottom=None, *, align="center",
23032303
label = kwargs.pop('label', '')
23042304
tick_labels = kwargs.pop('tick_label', None)
23052305

2306-
adjust_ylim = False
2307-
adjust_xlim = False
2308-
23092306
y = bottom # Matches barh call signature.
23102307
if orientation == 'vertical':
2311-
if bottom is None:
2312-
if self.get_yscale() == 'log':
2313-
adjust_ylim = True
2308+
if y is None:
23142309
y = 0
2315-
23162310
elif orientation == 'horizontal':
23172311
if x is None:
2318-
if self.get_xscale() == 'log':
2319-
adjust_xlim = True
23202312
x = 0
23212313

23222314
if orientation == 'vertical':
@@ -2429,21 +2421,6 @@ def bar(self, x, height, width=0.8, bottom=None, *, align="center",
24292421
else:
24302422
errorbar = None
24312423

2432-
if adjust_xlim:
2433-
xmin, xmax = self.dataLim.intervalx
2434-
xmin = min(w for w in width if w > 0)
2435-
if xerr is not None:
2436-
xmin = xmin - np.max(xerr)
2437-
xmin = max(xmin * 0.9, 1e-100)
2438-
self.dataLim.intervalx = (xmin, xmax)
2439-
2440-
if adjust_ylim:
2441-
ymin, ymax = self.dataLim.intervaly
2442-
ymin = min(h for h in height if h > 0)
2443-
if yerr is not None:
2444-
ymin = ymin - np.max(yerr)
2445-
ymin = max(ymin * 0.9, 1e-100)
2446-
self.dataLim.intervaly = (ymin, ymax)
24472424
self._request_autoscale_view()
24482425

24492426
bar_container = BarContainer(patches, errorbar, label=label)
@@ -6741,30 +6718,8 @@ def hist(self, x, bins=None, range=None, density=False, weights=None,
67416718
if log:
67426719
if orientation == 'horizontal':
67436720
self.set_xscale('log', nonposx='clip')
6744-
logbase = self.xaxis._scale.base
67456721
else: # orientation == 'vertical'
67466722
self.set_yscale('log', nonposy='clip')
6747-
logbase = self.yaxis._scale.base
6748-
6749-
# Setting a minimum of 0 results in problems for log plots
6750-
if np.min(bottom) > 0:
6751-
minimum = np.min(bottom)
6752-
elif density or weights is not None:
6753-
# For data that is normed to form a probability density,
6754-
# set to minimum data value / logbase
6755-
# (gives 1 full tick-label unit for the lowest filled bin)
6756-
ndata = np.array(tops)
6757-
minimum = (np.min(ndata[ndata > 0])) / logbase
6758-
else:
6759-
# For non-normed (density = False) data,
6760-
# set the min to 1 / log base,
6761-
# again so that there is 1 full tick-label unit
6762-
# for the lowest bin
6763-
minimum = 1.0 / logbase
6764-
6765-
y[0], y[-1] = minimum, minimum
6766-
else:
6767-
minimum = 0
67686723

67696724
if align == 'left':
67706725
x -= 0.5*(bins[1]-bins[0])
@@ -6785,8 +6740,6 @@ def hist(self, x, bins=None, range=None, density=False, weights=None,
67856740
# set the top of this polygon
67866741
y[1:2*len(bins)-1:2], y[2:2*len(bins):2] = (m + bottom,
67876742
m + bottom)
6788-
if log:
6789-
y[y < minimum] = minimum
67906743
if orientation == 'horizontal':
67916744
xvals.append(y.copy())
67926745
yvals.append(x.copy())
@@ -6809,9 +6762,9 @@ def hist(self, x, bins=None, range=None, density=False, weights=None,
68096762
for patch_list in patches:
68106763
for patch in patch_list:
68116764
if orientation == 'vertical':
6812-
patch.sticky_edges.y.append(minimum)
6765+
patch.sticky_edges.y.append(0)
68136766
elif orientation == 'horizontal':
6814-
patch.sticky_edges.x.append(minimum)
6767+
patch.sticky_edges.x.append(0)
68156768

68166769
# we return patches, so put it back in the expected order
68176770
patches.reverse()
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)