@@ -1476,7 +1476,8 @@ class MaxNLocator(Locator):
14761476 steps = None ,
14771477 integer = False ,
14781478 symmetric = False ,
1479- prune = None )
1479+ prune = None ,
1480+ min_n_ticks = 2 )
14801481
14811482 def __init__ (self , * args , ** kwargs ):
14821483 """
@@ -1508,6 +1509,11 @@ def __init__(self, *args, **kwargs):
15081509 removed. If prune=='both', the largest and smallest ticks
15091510 will be removed. If prune==None, no ticks will be removed.
15101511
1512+ *min_n_ticks*
1513+ While the estimated number of ticks is less than the minimum,
1514+ the target value *nbins* is incremented and the ticks are
1515+ recalculated.
1516+
15111517 """
15121518 if args :
15131519 kwargs ['nbins' ] = args [0 ]
@@ -1550,11 +1556,27 @@ def set_params(self, **kwargs):
15501556 self ._integer = kwargs ['integer' ]
15511557 if self ._integer :
15521558 self ._steps = [n for n in self ._steps if _divmod (n , 1 )[1 ] < 0.001 ]
1559+ if 'min_n_ticks' in kwargs :
1560+ self ._min_n_ticks = max (1 , kwargs ['min_n_ticks' ])
15531561
15541562 def _raw_ticks (self , vmin , vmax ):
1555- nbins = self ._nbins
1556- if nbins == 'auto' :
1557- nbins = max (min (self .axis .get_tick_space (), 9 ), 1 )
1563+ if self ._nbins == 'auto' :
1564+ nbins = max (min (self .axis .get_tick_space (), 9 ),
1565+ max (1 , self ._min_n_ticks - 1 ))
1566+ else :
1567+ nbins = self ._nbins
1568+
1569+ while True :
1570+ ticks = self ._try_raw_ticks (vmin , vmax , nbins )
1571+ nticks = ((ticks <= vmax ) & (ticks >= vmin )).sum ()
1572+ if nticks >= self ._min_n_ticks :
1573+ break
1574+ nbins += 1
1575+
1576+ self ._nbins_used = nbins # Maybe useful for troubleshooting.
1577+ return ticks
1578+
1579+ def _try_raw_ticks (self , vmin , vmax , nbins ):
15581580 scale , offset = scale_range (vmin , vmax , nbins )
15591581 if self ._integer :
15601582 scale = max (1 , scale )
@@ -1565,9 +1587,8 @@ def _raw_ticks(self, vmin, vmax):
15651587 best_vmax = vmax
15661588 best_vmin = vmin
15671589
1568- for step in self ._steps :
1569- if step < scaled_raw_step :
1570- continue
1590+ steps = (x for x in self ._steps if x >= scaled_raw_step )
1591+ for step in steps :
15711592 step *= scale
15721593 best_vmin = vmin // step * step
15731594 best_vmax = best_vmin + step * nbins
@@ -1603,11 +1624,10 @@ def tick_values(self, vmin, vmax):
16031624 return self .raise_if_exceeds (locs )
16041625
16051626 def view_limits (self , dmin , dmax ):
1606- if rcParams ['axes.autolimit_mode' ] == 'round_numbers' :
1607- if self ._symmetric :
1608- maxabs = max (abs (dmin ), abs (dmax ))
1609- dmin = - maxabs
1610- dmax = maxabs
1627+ if self ._symmetric :
1628+ maxabs = max (abs (dmin ), abs (dmax ))
1629+ dmin = - maxabs
1630+ dmax = maxabs
16111631
16121632 dmin , dmax = mtransforms .nonsingular (
16131633 dmin , dmax , expander = 1e-12 , tiny = 1e-13 )
@@ -2053,9 +2073,11 @@ class AutoLocator(MaxNLocator):
20532073 def __init__ (self ):
20542074 if rcParams ['_internal.classic_mode' ]:
20552075 nbins = 9
2076+ steps = [1 , 2 , 5 , 10 ]
20562077 else :
20572078 nbins = 'auto'
2058- MaxNLocator .__init__ (self , nbins = nbins , steps = [1 , 2 , 5 , 10 ])
2079+ steps = [1 , 2 , 2.5 , 5 , 10 ]
2080+ MaxNLocator .__init__ (self , nbins = nbins , steps = steps )
20592081
20602082
20612083class AutoMinorLocator (Locator ):
0 commit comments