@@ -1586,7 +1586,8 @@ class MaxNLocator(Locator):
15861586 steps = None ,
15871587 integer = False ,
15881588 symmetric = False ,
1589- prune = None )
1589+ prune = None ,
1590+ min_n_ticks = 2 )
15901591
15911592 def __init__ (self , * args , ** kwargs ):
15921593 """
@@ -1618,6 +1619,11 @@ def __init__(self, *args, **kwargs):
16181619 removed. If prune=='both', the largest and smallest ticks
16191620 will be removed. If prune==None, no ticks will be removed.
16201621
1622+ *min_n_ticks*
1623+ While the estimated number of ticks is less than the minimum,
1624+ the target value *nbins* is incremented and the ticks are
1625+ recalculated.
1626+
16211627 """
16221628 if args :
16231629 kwargs ['nbins' ] = args [0 ]
@@ -1660,11 +1666,27 @@ def set_params(self, **kwargs):
16601666 self ._integer = kwargs ['integer' ]
16611667 if self ._integer :
16621668 self ._steps = [n for n in self ._steps if _divmod (n , 1 )[1 ] < 0.001 ]
1669+ if 'min_n_ticks' in kwargs :
1670+ self ._min_n_ticks = max (1 , kwargs ['min_n_ticks' ])
16631671
16641672 def _raw_ticks (self , vmin , vmax ):
1665- nbins = self ._nbins
1666- if nbins == 'auto' :
1667- nbins = max (min (self .axis .get_tick_space (), 9 ), 1 )
1673+ if self ._nbins == 'auto' :
1674+ nbins = max (min (self .axis .get_tick_space (), 9 ),
1675+ max (1 , self ._min_n_ticks - 1 ))
1676+ else :
1677+ nbins = self ._nbins
1678+
1679+ while True :
1680+ ticks = self ._try_raw_ticks (vmin , vmax , nbins )
1681+ nticks = ((ticks <= vmax ) & (ticks >= vmin )).sum ()
1682+ if nticks >= self ._min_n_ticks :
1683+ break
1684+ nbins += 1
1685+
1686+ self ._nbins_used = nbins # Maybe useful for troubleshooting.
1687+ return ticks
1688+
1689+ def _try_raw_ticks (self , vmin , vmax , nbins ):
16681690 scale , offset = scale_range (vmin , vmax , nbins )
16691691 if self ._integer :
16701692 scale = max (1 , scale )
@@ -1675,9 +1697,8 @@ def _raw_ticks(self, vmin, vmax):
16751697 best_vmax = vmax
16761698 best_vmin = vmin
16771699
1678- for step in self ._steps :
1679- if step < scaled_raw_step :
1680- continue
1700+ steps = (x for x in self ._steps if x >= scaled_raw_step )
1701+ for step in steps :
16811702 step *= scale
16821703 best_vmin = vmin // step * step
16831704 best_vmax = best_vmin + step * nbins
@@ -1713,11 +1734,10 @@ def tick_values(self, vmin, vmax):
17131734 return self .raise_if_exceeds (locs )
17141735
17151736 def view_limits (self , dmin , dmax ):
1716- if rcParams ['axes.autolimit_mode' ] == 'round_numbers' :
1717- if self ._symmetric :
1718- maxabs = max (abs (dmin ), abs (dmax ))
1719- dmin = - maxabs
1720- dmax = maxabs
1737+ if self ._symmetric :
1738+ maxabs = max (abs (dmin ), abs (dmax ))
1739+ dmin = - maxabs
1740+ dmax = maxabs
17211741
17221742 dmin , dmax = mtransforms .nonsingular (
17231743 dmin , dmax , expander = 1e-12 , tiny = 1e-13 )
@@ -2163,9 +2183,11 @@ class AutoLocator(MaxNLocator):
21632183 def __init__ (self ):
21642184 if rcParams ['_internal.classic_mode' ]:
21652185 nbins = 9
2186+ steps = [1 , 2 , 5 , 10 ]
21662187 else :
21672188 nbins = 'auto'
2168- MaxNLocator .__init__ (self , nbins = nbins , steps = [1 , 2 , 5 , 10 ])
2189+ steps = [1 , 2 , 2.5 , 5 , 10 ]
2190+ MaxNLocator .__init__ (self , nbins = nbins , steps = steps )
21692191
21702192
21712193class AutoMinorLocator (Locator ):
0 commit comments