@@ -1674,7 +1674,9 @@ def __init__(self, *args, **kwargs):
1674
1674
e.g., [1, 2, 4, 5, 10]
1675
1675
1676
1676
*integer*
1677
- If True, ticks will take only integer values.
1677
+ If True, ticks will take only integer values, provided
1678
+ at least `min_n_ticks` integers are found within the
1679
+ view limits.
1678
1680
1679
1681
*symmetric*
1680
1682
If True, autoscaling will result in a range symmetric
@@ -1684,16 +1686,16 @@ def __init__(self, *args, **kwargs):
1684
1686
['lower' | 'upper' | 'both' | None]
1685
1687
Remove edge ticks -- useful for stacked or ganged plots
1686
1688
where the upper tick of one axes overlaps with the lower
1687
- tick of the axes above it.
1688
- If prune=='lower', the smallest tick will
1689
- be removed. If prune=='upper', the largest tick will be
1690
- removed. If prune=='both', the largest and smallest ticks
1691
- will be removed. If prune==None, no ticks will be removed.
1689
+ tick of the axes above it, primarily when
1690
+ `rcParams['axes.autolimit_mode']` is `'round_numbers'`.
1691
+ If `prune=='lower'`, the smallest tick will
1692
+ be removed. If `prune=='upper'`, the largest tick will be
1693
+ removed. If `prune=='both'`, the largest and smallest ticks
1694
+ will be removed. If `prune==None`, no ticks will be removed.
1692
1695
1693
1696
*min_n_ticks*
1694
- While the estimated number of ticks is less than the minimum,
1695
- the target value *nbins* is incremented and the ticks are
1696
- recalculated.
1697
+ Relax `nbins` and `integer` constraints if necessary to
1698
+ obtain this minimum number of ticks.
1697
1699
1698
1700
"""
1699
1701
if args :
@@ -1714,8 +1716,6 @@ def set_params(self, **kwargs):
1714
1716
warnings .warn (
1715
1717
"The 'trim' keyword has no effect since version 2.0." ,
1716
1718
mplDeprecation )
1717
- if 'integer' in kwargs :
1718
- self ._integer = kwargs ['integer' ]
1719
1719
if 'symmetric' in kwargs :
1720
1720
self ._symmetric = kwargs ['symmetric' ]
1721
1721
if 'prune' in kwargs :
@@ -1733,6 +1733,13 @@ def set_params(self, **kwargs):
1733
1733
steps = list (steps )
1734
1734
steps .append (10 )
1735
1735
self ._steps = steps
1736
+ # Make an extended staircase within which the needed
1737
+ # step will be found. This is probably much larger
1738
+ # than necessary.
1739
+ flights = (0.1 * np .array (self ._steps [:- 1 ]),
1740
+ self ._steps ,
1741
+ [10 * self ._steps [1 ]])
1742
+ self ._extended_steps = np .hstack (flights )
1736
1743
if 'integer' in kwargs :
1737
1744
self ._integer = kwargs ['integer' ]
1738
1745
if self ._integer :
@@ -1747,42 +1754,38 @@ def _raw_ticks(self, vmin, vmax):
1747
1754
else :
1748
1755
nbins = self ._nbins
1749
1756
1750
- while True :
1751
- ticks = self ._try_raw_ticks (vmin , vmax , nbins )
1757
+ scale , offset = scale_range (vmin , vmax , nbins )
1758
+ _vmin = vmin - offset
1759
+ _vmax = vmax - offset
1760
+ raw_step = (vmax - vmin ) / nbins
1761
+ steps = self ._extended_steps * scale
1762
+ istep = np .nonzero (steps >= raw_step )[0 ][0 ]
1763
+
1764
+ # Classic round_numbers mode may require a larger step.
1765
+ if rcParams ['axes.autolimit_mode' ] == 'round_numbers' :
1766
+ for istep in range (istep , len (steps )):
1767
+ step = steps [istep ]
1768
+ best_vmin = (_vmin // step ) * step
1769
+ best_vmax = best_vmin + step * nbins
1770
+ if (best_vmax >= _vmax ):
1771
+ break
1772
+
1773
+ # This is an upper limit; move to smaller steps if necessary.
1774
+ for i in range (istep ):
1775
+ step = steps [istep - i ]
1776
+ if (self ._integer and
1777
+ np .floor (_vmax ) - np .ceil (_vmin ) >= self ._min_n_ticks - 1 ):
1778
+ step = max (1 , step )
1779
+ best_vmin = (_vmin // step ) * step
1780
+
1781
+ low = round (Base (step ).le (_vmin - best_vmin ) / step )
1782
+ high = round (Base (step ).ge (_vmax - best_vmin ) / step )
1783
+ ticks = np .arange (low , high + 1 ) * step + best_vmin + offset
1752
1784
nticks = ((ticks <= vmax ) & (ticks >= vmin )).sum ()
1753
1785
if nticks >= self ._min_n_ticks :
1754
1786
break
1755
- nbins += 1
1756
-
1757
- self ._nbins_used = nbins # Maybe useful for troubleshooting.
1758
1787
return ticks
1759
1788
1760
- def _try_raw_ticks (self , vmin , vmax , nbins ):
1761
- scale , offset = scale_range (vmin , vmax , nbins )
1762
- if self ._integer :
1763
- scale = max (1 , scale )
1764
- vmin = vmin - offset
1765
- vmax = vmax - offset
1766
- raw_step = (vmax - vmin ) / nbins
1767
- scaled_raw_step = raw_step / scale
1768
- best_vmax = vmax
1769
- best_vmin = vmin
1770
-
1771
- steps = (x for x in self ._steps if x >= scaled_raw_step )
1772
- for step in steps :
1773
- step *= scale
1774
- best_vmin = vmin // step * step
1775
- best_vmax = best_vmin + step * nbins
1776
- if best_vmax >= vmax :
1777
- break
1778
-
1779
- # More than nbins may be required, e.g. vmin, vmax = -4.1, 4.1 gives
1780
- # nbins=9 but 10 bins are actually required after rounding. So we just
1781
- # create the bins that span the range we need instead.
1782
- low = round (Base (step ).le (vmin - best_vmin ) / step )
1783
- high = round (Base (step ).ge (vmax - best_vmin ) / step )
1784
- return np .arange (low , high + 1 ) * step + best_vmin + offset
1785
-
1786
1789
@cbook .deprecated ("2.0" )
1787
1790
def bin_boundaries (self , vmin , vmax ):
1788
1791
return self ._raw_ticks (vmin , vmax )
0 commit comments