Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e2315d2

Browse files
committed
Merge pull request #4330 from has2k1/date-locators
ENH/API : Add tick_values method to the date Locators
2 parents 3afb042 + 2971dec commit e2315d2

File tree

3 files changed

+73
-18
lines changed

3 files changed

+73
-18
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Removed `args` and `kwargs` from `MicrosecondLocator.__call__`
2+
``````````````````````````````````````````````````````````````
3+
4+
The call signature of :meth:`~matplotlib.dates.MicrosecondLocator.__call__`
5+
has changed from `__call__(self, *args, **kwargs)` to `__call__(self)`.
6+
This is consistent with the super class :class:`~matplotlib.ticker.Locator`
7+
and also all the other Locators derived from this super class.
8+
9+
10+
No `ValueError` for the MicrosecondLocator and YearLocator
11+
``````````````````````````````````````````````````````````
12+
13+
The :class:`~matplotlib.dates.MicrosecondLocator` and
14+
:class:`~matplotlib.dates.YearLocator` objects when called will return
15+
an empty list if the axes have no data or the view has no interval.
16+
Previously, they raised a `ValueError`. This is consistent with all
17+
the Date Locators.

doc/users/whats_new/datelocators.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Date Locators
2+
-------------
3+
4+
Date Locators (derived from :class:`~matplotlib.dates.DateLocator`) now
5+
implement the :meth:`~matplotlib.tickers.Locator.tick_values` method.
6+
This is expected of all Locators derived from :class:`~matplotlib.tickers.Locator`.
7+
8+
The Date Locators can now be used easily without creating axes
9+
10+
from datetime import datetime
11+
from matplotlib.dates import YearLocator
12+
t0 = datetime(2002, 10, 9, 12, 10)
13+
tf = datetime(2005, 10, 9, 12, 15)
14+
loc = YearLocator()
15+
values = loc.tick_values(t0, tf)

lib/matplotlib/dates.py

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -667,18 +667,21 @@ def __call__(self):
667667
except ValueError:
668668
return []
669669

670-
if dmin > dmax:
671-
dmax, dmin = dmin, dmax
672-
delta = relativedelta(dmax, dmin)
670+
return self.tick_values(dmin, dmax)
671+
672+
def tick_values(self, vmin, vmax):
673+
if vmin > vmax:
674+
vmax, vmin = vmin, vmax
675+
delta = relativedelta(vmax, vmin)
673676

674677
# We need to cap at the endpoints of valid datetime
675678
try:
676-
start = dmin - delta
679+
start = vmin - delta
677680
except ValueError:
678681
start = _from_ordinalf(1.0)
679682

680683
try:
681-
stop = dmax + delta
684+
stop = vmax + delta
682685
except ValueError:
683686
# The magic number!
684687
stop = _from_ordinalf(3652059.9999999)
@@ -688,19 +691,19 @@ def __call__(self):
688691
# estimate the number of ticks very approximately so we don't
689692
# have to do a very expensive (and potentially near infinite)
690693
# 'between' calculation, only to find out it will fail.
691-
nmax, nmin = date2num((dmax, dmin))
694+
nmax, nmin = date2num((vmax, vmin))
692695
estimate = (nmax - nmin) / (self._get_unit() * self._get_interval())
693696
# This estimate is only an estimate, so be really conservative
694697
# about bailing...
695698
if estimate > self.MAXTICKS * 2:
696699
raise RuntimeError(
697700
'RRuleLocator estimated to generate %d ticks from %s to %s: '
698-
'exceeds Locator.MAXTICKS * 2 (%d) ' % (estimate, dmin, dmax,
701+
'exceeds Locator.MAXTICKS * 2 (%d) ' % (estimate, vmin, vmax,
699702
self.MAXTICKS * 2))
700703

701-
dates = self.rule.between(dmin, dmax, True)
704+
dates = self.rule.between(vmin, vmax, True)
702705
if len(dates) == 0:
703-
return date2num([dmin, dmax])
706+
return date2num([vmin, vmax])
704707
return self.raise_if_exceeds(date2num(dates))
705708

706709
def _get_unit(self):
@@ -866,6 +869,9 @@ def __call__(self):
866869
self.refresh()
867870
return self._locator()
868871

872+
def tick_values(self, vmin, vmax):
873+
return self.get_locator(vmin, vmax).tick_values(vmin, vmax)
874+
869875
def nonsingular(self, vmin, vmax):
870876
# whatever is thrown at us, we can scale the unit.
871877
# But default nonsingular date plots at an ~4 year period.
@@ -1012,11 +1018,19 @@ def __init__(self, base=1, month=1, day=1, tz=None):
10121018
}
10131019

10141020
def __call__(self):
1015-
dmin, dmax = self.viewlim_to_dt()
1016-
ymin = self.base.le(dmin.year)
1017-
ymax = self.base.ge(dmax.year)
1021+
# if no data have been set, this will tank with a ValueError
1022+
try:
1023+
dmin, dmax = self.viewlim_to_dt()
1024+
except ValueError:
1025+
return []
1026+
1027+
return self.tick_values(dmin, dmax)
1028+
1029+
def tick_values(self, vmin, vmax):
1030+
ymin = self.base.le(vmin.year)
1031+
ymax = self.base.ge(vmax.year)
10181032

1019-
ticks = [dmin.replace(year=ymin, **self.replaced)]
1033+
ticks = [vmin.replace(year=ymin, **self.replaced)]
10201034
while 1:
10211035
dt = ticks[-1]
10221036
if dt.year >= ymax:
@@ -1184,11 +1198,20 @@ def set_data_interval(self, vmin, vmax):
11841198
self._wrapped_locator.set_data_interval(vmin, vmax)
11851199
return DateLocator.set_data_interval(self, vmin, vmax)
11861200

1187-
def __call__(self, *args, **kwargs):
1188-
vmin, vmax = self.axis.get_view_interval()
1189-
vmin *= MUSECONDS_PER_DAY
1190-
vmax *= MUSECONDS_PER_DAY
1191-
ticks = self._wrapped_locator.tick_values(vmin, vmax)
1201+
def __call__(self):
1202+
# if no data have been set, this will tank with a ValueError
1203+
try:
1204+
dmin, dmax = self.viewlim_to_dt()
1205+
except ValueError:
1206+
return []
1207+
1208+
return self.tick_values(dmin, dmax)
1209+
1210+
def tick_values(self, vmin, vmax):
1211+
nmin, nmax = date2num((vmin, vmax))
1212+
nmin *= MUSECONDS_PER_DAY
1213+
nmax *= MUSECONDS_PER_DAY
1214+
ticks = self._wrapped_locator.tick_values(nmin, nmax)
11921215
ticks = [tick / MUSECONDS_PER_DAY for tick in ticks]
11931216
return ticks
11941217

0 commit comments

Comments
 (0)