@@ -1674,7 +1674,9 @@ def __init__(self, *args, **kwargs):
16741674 e.g., [1, 2, 4, 5, 10]
16751675
16761676 *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.
16781680
16791681 *symmetric*
16801682 If True, autoscaling will result in a range symmetric
@@ -1684,16 +1686,16 @@ def __init__(self, *args, **kwargs):
16841686 ['lower' | 'upper' | 'both' | None]
16851687 Remove edge ticks -- useful for stacked or ganged plots
16861688 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.
16921695
16931696 *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.
16971699
16981700 """
16991701 if args :
@@ -1714,8 +1716,6 @@ def set_params(self, **kwargs):
17141716 warnings .warn (
17151717 "The 'trim' keyword has no effect since version 2.0." ,
17161718 mplDeprecation )
1717- if 'integer' in kwargs :
1718- self ._integer = kwargs ['integer' ]
17191719 if 'symmetric' in kwargs :
17201720 self ._symmetric = kwargs ['symmetric' ]
17211721 if 'prune' in kwargs :
@@ -1733,6 +1733,13 @@ def set_params(self, **kwargs):
17331733 steps = list (steps )
17341734 steps .append (10 )
17351735 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 )
17361743 if 'integer' in kwargs :
17371744 self ._integer = kwargs ['integer' ]
17381745 if self ._integer :
@@ -1747,42 +1754,38 @@ def _raw_ticks(self, vmin, vmax):
17471754 else :
17481755 nbins = self ._nbins
17491756
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
17521784 nticks = ((ticks <= vmax ) & (ticks >= vmin )).sum ()
17531785 if nticks >= self ._min_n_ticks :
17541786 break
1755- nbins += 1
1756-
1757- self ._nbins_used = nbins # Maybe useful for troubleshooting.
17581787 return ticks
17591788
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-
17861789 @cbook .deprecated ("2.0" )
17871790 def bin_boundaries (self , vmin , vmax ):
17881791 return self ._raw_ticks (vmin , vmax )
0 commit comments