[Scipy-svn] r2769 - trunk/Lib/sandbox/timeseries/plotlib
scipy-svn at scipy.org
scipy-svn at scipy.org
Tue Feb 27 09:05:05 EST 2007
Author: mattknox_ca
Date: 2007-02-27 08:05:02 -0600 (Tue, 27 Feb 2007)
New Revision: 2769
Modified:
trunk/Lib/sandbox/timeseries/plotlib/mpl_timeseries.py
Log:
major overhaul
Modified: trunk/Lib/sandbox/timeseries/plotlib/mpl_timeseries.py
===================================================================
--- trunk/Lib/sandbox/timeseries/plotlib/mpl_timeseries.py 2007-02-27 14:02:11 UTC (rev 2768)
+++ trunk/Lib/sandbox/timeseries/plotlib/mpl_timeseries.py 2007-02-27 14:05:02 UTC (rev 2769)
@@ -1,12 +1,12 @@
"""
Classes to plot TimeSeries w/ matplotlib.
-:author: Pierre GF Gerard-Marchant
-:contact: pierregm_at_uga_edu
+:author: Pierre GF Gerard-Marchant & Matt Knox
+:contact: pierregm_at_uga_dot_edu - mattknow_ca_at_hotmail_dot_com
:date: $Date$
:version: $Id$
"""
-__author__ = "Pierre GF Gerard-Marchant ($Author$)"
+__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author$)"
__version__ = '1.0'
__revision__ = "$Revision$"
__date__ = '$Date$'
@@ -26,17 +26,14 @@
from matplotlib.mlab import meshgrid
from matplotlib.ticker import Formatter, ScalarFormatter, FuncFormatter, \
Locator, FixedLocator
-
#from matplotlib.transforms import nonsingular
import numpy as N
import maskedarray as MA
import timeseries
+import timeseries as TS
from timeseries import date_array, Date, DateArray, TimeSeries
-#from tdates import date_array, Date
-#import tseries
-#from tseries import TimeSeries
import warnings
@@ -133,207 +130,366 @@
def _get_default_annual_spacing(nyears):
"""Returns a default spacing between consecutive ticks for annual data."""
- if nyears < 20:
+ if nyears < 11:
+ (min_spacing, maj_spacing) = (1, 1)
+ elif nyears < 20:
(min_spacing, maj_spacing) = (1, 2)
elif nyears < 50:
(min_spacing, maj_spacing) = (1, 5)
elif nyears < 100:
(min_spacing, maj_spacing) = (5, 10)
elif nyears < 200:
- (min_spacing, maj_spacing) = (5, 20)
- elif nyears < 400:
(min_spacing, maj_spacing) = (5, 25)
- elif nyears < 1000:
+ elif nyears < 600:
(min_spacing, maj_spacing) = (10, 50)
else:
- (min_spacing, maj_spacing) = (20, 100)
+ factor = nyears // 1000 + 1
+ (min_spacing, maj_spacing) = (factor*20, factor*100)
return (min_spacing, maj_spacing)
-def _get_default_quarterly_spacing(nquarters):
- """Returns a default spacing between consecutive ticks for quarterly data."""
- if nquarters <= 3*4:
- (min_spacing, maj_spacing) = (1,4)
- elif nquarters <= 11*4:
- (min_spacing, maj_spacing) = (1,4)
+
+def period_break(dates, period):
+ """Returns the indices where the given period changes.
+
+:Parameters:
+ dates : DateArray
+ Array of dates to monitor.
+ period : string
+ Name of the period to monitor.
+ """
+ current = getattr(dates, period)
+ previous = getattr(dates-1, period)
+ return (current - previous).nonzero()[0]
+
+def has_level_label(label_flags):
+ """returns true if the label_flags indicate there is at least
+one label for this level"""
+ if label_flags.size == 0 or \
+ (label_flags.size == 1 and label_flags[0] == 0):
+ return False
else:
- (min_anndef, maj_anndef) = _get_default_annual_spacing(nquarters//4)
- min_spacing = min_anndef * 4
- maj_spacing = maj_anndef * 4
- return (min_spacing, maj_spacing)
+ return True
-def _get_default_monthly_spacing(nmonths):
- """Returns a default spacing between consecutive ticks for monthly data."""
- if nmonths <= 10:
- (min_spacing, maj_spacing) = (1,3)
- elif nmonths <= 2*12:
- (min_spacing, maj_spacing) = (1,6)
- elif nmonths <= 3*12:
- (min_spacing, maj_spacing) = (1,12)
- elif nmonths <= 11*12:
- (min_spacing, maj_spacing) = (3,12)
+def _daily_finder(vmin, vmax, freq, aslocator):
+
+ if freq == TS.FR_BUS:
+ periodsperyear = 261
+ elif freq == TS.FR_DAY:
+ periodsperyear = 365
+ else:
+ raise ValueError("unexpected frequency")
+
+ (vmin, vmax) = (int(vmin), int(vmax))
+ span = vmax - vmin + 1
+ dates = date_array(start_date=Date(freq,vmin),
+ end_date=Date(freq, vmax))
+ default = N.arange(vmin, vmax+1)
+ # Initialize the output
+ if not aslocator:
+ format = N.empty(default.shape, dtype="|S10")
+ format.flat = ''
+
+ def first_label(label_flags):
+ if label_flags[0] == 0: return label_flags[1]
+ else: return label_flags[0]
+
+ # Case 1. Less than a month
+ if span <= (periodsperyear//12 - 2):
+ month_start = period_break(dates,'month')
+ if aslocator:
+ major = default[month_start]
+ minor = default
+ else:
+ year_start = period_break(dates,'year')
+ format[:] = '%d'
+ format[month_start] = '%d\n%b'
+ format[year_start] = '%d\n%b\n%Y'
+ if not has_level_label(year_start):
+ if not has_level_label(month_start):
+ if dates.size > 1:
+ idx = 1
+ else:
+ idx = 0
+ format[idx] = '%d\n%b\n%Y'
+ else:
+ format[first_label(month_start)] = '%d\n%b\n%Y'
+ # Case 2. Less than three months
+ elif span <= periodsperyear//4:
+ month_start = period_break(dates,'month')
+ if aslocator:
+ major = default[month_start]
+ minor = default
+ else:
+ week_start = period_break(dates,'week')
+ year_start = period_break(dates,'year')
+
+ format[week_start] = '%d'
+ format[month_start] = '\n\n%b'
+ format[year_start] = '\n\n%b\n%Y'
+ if not has_level_label(year_start):
+ if not has_level_label(month_start):
+ format[first_label(week_start)] = '\n\n%b\n%Y'
+ else:
+ format[first_label(month_start)] = '\n\n%b\n%Y'
+ # Case 3. Less than 14 months ...............
+ elif span <= 1.15 * periodsperyear:
+
+ if aslocator:
+ d_minus_1 = dates-1
+
+ month_diff = N.abs(dates.month - d_minus_1.month)
+ week_diff = N.abs(dates.week - d_minus_1.week)
+ minor_idx = (month_diff + week_diff).nonzero()[0]
+
+ major = default[month_diff != 0]
+ minor = default[minor_idx]
+ else:
+ year_start = period_break(dates,'year')
+ month_start = period_break(dates,'month')
+
+ format[month_start] = '%b'
+ format[year_start] = '%b\n%Y'
+ if not has_level_label(year_start):
+ format[first_label(month_start)] = '%b\n%Y'
+ # Case 4. Less than 2.5 years ...............
+ elif span <= 2.5 * periodsperyear:
+ year_start = period_break(dates,'year')
+ if aslocator:
+ month_start = period_break(dates, 'quarter')
+ major = default[year_start]
+ minor = default[month_start]
+ else:
+ quarter_start = period_break(dates, 'quarter')
+ format[quarter_start] = '%b'
+ format[year_start] = '%b\n%Y'
+ # Case 4. Less than 4 years .................
+ elif span <= 4 * periodsperyear:
+ year_start = period_break(dates,'year')
+ month_start = period_break(dates, 'month')
+ if aslocator:
+ major = default[year_start]
+ minor = default[month_start]
+ else:
+ month_break = dates[month_start].month
+ jan_or_jul = month_start[(month_break == 1) | (month_break == 7)]
+ format[jan_or_jul] = '%b'
+ format[year_start] = '%b\n%Y'
+ # Case 5. Less than 11 years ................
+ elif span <= 11 * periodsperyear:
+ year_start = period_break(dates,'year')
+ if aslocator:
+ quarter_start = period_break(dates, 'quarter')
+ major = default[year_start]
+ minor = default[quarter_start]
+ else:
+ format[year_start] = '%Y'
+ # Case 6. More than 12 years ................
else:
- (min_anndef, maj_anndef) = _get_default_annual_spacing(nmonths//12)
- min_spacing = min_anndef * 12
- maj_spacing = maj_anndef * 12
- return (min_spacing, maj_spacing)
+ year_start = period_break(dates,'year')
+ year_break = dates[year_start].years
+ nyears = span/periodsperyear
+ (min_anndef, maj_anndef) = _get_default_annual_spacing(nyears)
+ major_idx = year_start[(year_break % maj_anndef == 0)]
+ if aslocator:
+ major = default[major_idx]
+ minor_idx = year_start[(year_break % min_anndef == 0)]
+ minor = default[minor_idx]
+ else:
+ format[major_idx] = '%Y'
+ #............................................
+ if aslocator:
+ return minor, major
+ else:
+ formatted = (format != '')
+ return dict([(d,f) for (d,f) in zip(default[formatted],format[formatted])])
+#...............................................................................
+def _monthly_finder(vmin, vmax, freq, aslocator):
+ if freq != TS.FR_MTH:
+ raise ValueError("unexpected frequency")
+ periodsperyear = 12
+ (vmin, vmax) = (int(vmin), int(vmax))
+ span = vmax - vmin + 1
+ #............................................
+ dates = N.arange(vmin, vmax+1)
+ format = N.empty(span, dtype="|S8")
+ format.flat = ''
+ year_start = (dates % 12 == 1).nonzero()[0]
+ #............................................
+ if span <= 1.15 * periodsperyear:
+ if aslocator:
+ major = dates[year_start]
+ minor = dates
+ else:
+
+ format[:] = '%b'
+ format[year_start] = '%b\n%Y'
+
+ if not has_level_label(year_start):
+ if dates.size > 1:
+ idx = 1
+ else:
+ idx = 0
+ format[idx] = '%b\n%Y'
+ #........................
+ elif span <= 2.5 * periodsperyear:
+ if aslocator:
+ major = dates[year_start]
+ minor = dates
+ else:
+ quarter_start = (dates % 3 == 1).nonzero()
+ format[quarter_start] = '%b'
+ format[year_start] = '%b\n%Y'
+ #.......................
+ elif span <= 4 * periodsperyear:
+ if aslocator:
+ major = dates[year_start]
+ minor = dates
+ else:
+ jan_or_jul = (dates % 12 == 1) | (dates % 12 == 7)
+ format[jan_or_jul] = '%b'
+ format[year_start] = '%b\n%Y'
+ #........................
+ elif span <= 11 * periodsperyear:
+ if aslocator:
+ quarter_start = (dates % 3 == 1).nonzero()
+ major = dates[year_start]
+ minor = dates[quarter_start]
+ else:
+ format[year_start] = '%Y'
+ #.........................
+ else:
+ nyears = span/periodsperyear
+ (min_anndef, maj_anndef) = _get_default_annual_spacing(nyears)
+ years = dates[year_start]//12 + 1
+ major_idx = year_start[(years % maj_anndef == 0)]
+ if aslocator:
+ major = dates[major_idx]
+ minor = dates[year_start[(years % min_anndef == 0)]]
+ else:
+ format[major_idx] = '%Y'
+ #........................
+ if aslocator:
+ return minor, major
+ else:
+ formatted = (format != '')
+ return dict([(d,f) for (d,f) in zip(dates[formatted],format[formatted])])
#...............................................................................
+def _quarterly_finder(vmin, vmax, freq, aslocator):
+ if freq != TS.FR_QTR:
+ raise ValueError("unexpected frequency")
+ periodsperyear = 4
+ (vmin, vmax) = (int(vmin), int(vmax))
+ span = vmax - vmin + 1
+ #............................................
+ dates = N.arange(vmin, vmax+1)
+ format = N.empty(span, dtype="|S8")
+ format.flat = ''
+ year_start = (dates % 4 == 1).nonzero()[0]
+ #............................................
+ if span <= 3.5 * periodsperyear:
+ if aslocator:
+ major = dates[year_start]
+ minor = dates
+ else:
+ format[:] = 'Q%q'
+ format[year_start] = 'Q%q\n%Y'
+ if not has_level_label(year_start):
+ if dates.size > 1:
+ idx = 1
+ else:
+ idx = 0
+ format[idx] = 'Q%q\n%Y'
+ #............................................
+ elif span <= 11 * periodsperyear:
+ if aslocator:
+ major = dates[year_start]
+ minor = dates
+ else:
+ format[year_start] = '%Y'
+ #............................................
+ else:
+ years = dates[year_start]//4 + 1
+ nyears = span/periodsperyear
+ (min_anndef, maj_anndef) = _get_default_annual_spacing(nyears)
+ major_idx = year_start[(years % maj_anndef == 0)]
+ if aslocator:
+ major = dates[major_idx]
+ minor = dates[year_start[(years % min_anndef == 0)]]
+ else:
+ format[major_idx] = '%Y'
+ #............................................
+ if aslocator:
+ return minor, major
+ else:
+ formatted = (format != '')
+ return dict([(d,f) for (d,f) in zip(dates[formatted],format[formatted])])
+#...............................................................................
+def _annual_finder(vmin, vmax, freq, aslocator):
+ if freq != TS.FR_ANN:
+ raise ValueError("unexpected frequency")
+ (vmin, vmax) = (int(vmin), int(vmax+1))
+ span = vmax - vmin + 1
+ #............................................
+ dates = N.arange(vmin, vmax+1)
+ format = N.empty(span, dtype="|S8")
+ format.flat = ''
+ #............................................
+ (min_anndef, maj_anndef) = _get_default_annual_spacing(span)
+ major_idx = dates % maj_anndef == 0
+ if aslocator:
+ major = dates[major_idx]
+ minor = dates[(dates % min_anndef == 0)]
+ else:
+ format[major_idx] = '%Y'
+ #............................................
+ if aslocator:
+ return minor, major
+ else:
+ formatted = (format != '')
+ return dict([(d,f) for (d,f) in zip(dates[formatted],format[formatted])])
+
+#...............................................................................
class TimeSeries_DateLocator(Locator):
"Locates the ticks along an axis controlled by a DateArray."
def __init__(self, freq, minor_locator=False, dynamic_mode=True,
base=1, quarter=1, month=1, day=1):
- self.freqstr = freq
+ self.freq = freq
self.base = base
(self.quarter, self.month, self.day) = (quarter, month, day)
self.isminor = minor_locator
self.isdynamic = dynamic_mode
self.offset = 0
+ #.....
+ if freq == TS.FR_ANN:
+ self.finder = _annual_finder
+ elif freq == TS.FR_QTR:
+ self.finder = _quarterly_finder
+ elif freq == TS.FR_MTH:
+ self.finder = _monthly_finder
+ elif freq in (TS.FR_BUS, TS.FR_DAY):
+ self.finder = _daily_finder
- def _initialize_dates(self, start_val, end_val):
- "Returns a DateArray for the current frequency."
- freq = self.freqstr
- dates = date_array(start_date=Date(freq, value=int(start_val)),
- end_date=Date(freq, value=int(end_val)),
- freq=freq)
- return dates
-
- def _get_default_spacing(self, span):
- "Returns the default ticks spacing."
- raise NotImplementedError('Derived must override')
+ def asminor(self):
+ "Returns the locator set to minor mode."
+ self.isminor = True
+ return self
- def __call__(self):
- 'Return the locations of the ticks.'
- self.verify_intervals()
- vmin, vmax = self.viewInterval.get_bounds()
- if vmax < vmin:
- vmin, vmax = vmax, vmin
- if self.isdynamic:
- base = self._get_default_spacing(vmax-vmin+1)
- else:
- base = self.base
- d = vmin // base
- vmin = (d+1) * base + self.offset
- locs = range(vmin, vmax+1, base)
- return locs
+ def asmajor(self):
+ "Returns the locator set to major mode."
+ self.isminor = False
+ return self
- def autoscale(self):
- """Sets the view limits to the nearest multiples of base that contain
- the data.
- """
- self.verify_intervals()
- dmin, dmax = self.dataInterval.get_bounds()
- if self.isdynamic:
- base = self._get_default_spacing(dmax-dmin+1)
- else:
- base = self.base
- (d,m) = divmod(dmin, base)
- if m < base/2:
- vmin = d * base
- else:
- vmin = (d+1) * base
- (d,m) = divmod(dmax, base)
- vmax = (d+1) * base
- if vmin == vmax:
- vmin -= 1
- vmax += 1
- return nonsingular(vmin, vmax)
-
-#...............................................................................
-class TimeSeries_AnnualLocator(TimeSeries_DateLocator):
- "Locates the ticks along an axis controlled by an annual DateArray."
-
- def __init__(self, minor_locator=False, dynamic_mode=True,
- base=1, quarter=1, month=1, day=1):
- TimeSeries_DateLocator.__init__(self,'A', minor_locator, dynamic_mode,
- base, quarter, month, day)
-
- def _get_default_spacing(self, span):
- "Returns the default tick spacing for annual data."
- (minor, major) = _get_default_annual_spacing(span)
+ def _get_default_locs(self, vmin, vmax):
+ "Returns the default locations of ticks."
+ (minor, major) = self.finder(vmin, vmax, self.freq, True)
if self.isminor:
return minor
return major
-#...............................................................................
-class TimeSeries_QuarterlyLocator(TimeSeries_DateLocator):
- "Locates the ticks along an axis controlled by a quarterly DateArray."
-
- def __init__(self, minor_locator=False, dynamic_mode=True,
- base=1, quarter=1, month=1, day=1):
- TimeSeries_DateLocator.__init__(self,'Q', minor_locator, dynamic_mode,
- base, quarter, month, day)
- self.offset=1
- def _get_default_spacing(self, span):
- "Returns the default tick spacing for quarterly data."
- (minor, major) = _get_default_quarterly_spacing(span)
- if self.isminor:
- return minor
- return major
-#...............................................................................
-class TimeSeries_MonthlyLocator(TimeSeries_DateLocator):
- "Locates the ticks along an axis controlled by a monthly DateArray."
-
- def __init__(self, minor_locator=False, dynamic_mode=True,
- base=1, quarter=1, month=1, day=1):
- TimeSeries_DateLocator.__init__(self,'M', minor_locator, dynamic_mode,
- base, quarter, month, day)
- self.offset = 1
-
- def _get_default_spacing(self, span):
- "Returns the default tick spacing for monthly data."
- (minor, major) = _get_default_monthly_spacing(span)
- if self.isminor:
- return minor
- return major
-
-#...............................................................................
-class TimeSeries_DailyLocator(TimeSeries_DateLocator):
- "Locates the ticks along an axis controlled by a daily DateArray."
-
- def __init__(self, freq, minor_locator=False, dynamic_mode=True,
- base=1, quarter=1, month=1, day=1):
- TimeSeries_DateLocator.__init__(self, freq, minor_locator, dynamic_mode,
- base, quarter, month, day)
- if self.freqstr == 'B':
- self.daysinyear = 261
- else:
- self.daysinyear = 365
- self._cacheddates = None
-
- def _get_default_locs(self, vmin, vmax):
- "Returns the default tick locations for daily data."
- daysperyear = self.daysinyear
- span = vmax - vmin + 1
- dates = self._initialize_dates(vmin, vmax)
- default = N.arange(vmin, vmax+1)
- #
- if span <= daysperyear//12:
- minor = default
- major = default[(dates.day_of_week == 1)]
- elif span <= daysperyear//3:
- minor = default[(dates.day_of_week == 1)]
- major = default[(dates.day == 1)]
- elif span <= 1.5 * daysperyear:
- minor = default[(dates.day_of_week == 1)]
- major = default[(dates.day == 1)]
- elif span <= 3 * daysperyear:
- minor = default[(dates.day == 1)]
- major = default[(dates.day_of_year == 1)]
- elif span <= 11 * daysperyear:
- minor = default[(dates.quarter != (dates-1).quarter)]
- major = default[(dates.day_of_year == 1)]
- else:
- (min_anndef, maj_anndef) = _get_default_annual_spacing(span/daysperyear)
- annual = (dates.day_of_year == 1)
- minor = default[annual & (dates.years % min_anndef == 0)]
- major = default[annual & (dates.years % maj_anndef == 0)]
- if self.isminor:
- return minor
- return major
-
def __call__(self):
- 'Return the locations of the ticks'
+ 'Return the locations of the ticks.'
self.verify_intervals()
vmin, vmax = self.viewInterval.get_bounds()
if vmax < vmin:
@@ -342,11 +498,11 @@
locs = self._get_default_locs(vmin, vmax)
else:
base = self.base
- (d,m) = divmod(vmin, base)
+ (d, m) = divmod(vmin, base)
vmin = (d+1) * base
locs = range(vmin, vmax+1, base)
return locs
-
+
def autoscale(self):
"""Sets the view limits to the nearest multiples of base that contain
the data.
@@ -354,137 +510,72 @@
self.verify_intervals()
dmin, dmax = self.dataInterval.get_bounds()
locs = self._get_default_locs(dmin, dmax)
- (vmin, vmax) = locs[[0,-1]]
+ (vmin, vmax) = locs[[0, -1]]
if vmin == vmax:
vmin -= 1
vmax += 1
- return nonsingular(vmin, vmax)
+ return nonsingular(vmin, vmax)
-#...............................................................................
-class TimeSeries_YearLocator(TimeSeries_DateLocator):
- """Locates ticks along a Date axis, for each (multiple of) year.
-
-:Ivariables:
- - `base` : Integer
- Gives the spacing between two consecutive annual ticks.
- - `quarter` : Integer *[1]*
- Tells on which quarter the ticks should be.
- - `month` : Integer *[1]*
- Tells on which month the ticks should be.
- - `day` : Integer *[1]*
- Tells on which day the ticks should be.
- """
- def __init__(self, freq, minor_locator=False,
- base=1, quarter=1, month=1, day=1):
- TimeSeries_DateLocator.__init__(self, freq, minor_locator, False,
- base, quarter, month, day)
-
- def __call__(self):
- self.verify_intervals()
- vmin, vmax = self.viewInterval.get_bounds()
- freq = self.freqstr
- if freq == 'A':
- return range(vmin, vmax+1, self.base)
- else:
- dates = self._initialize_dates()
- if freq == 'Q':
- locs = (dates.quarters == self.quarter)
- elif freq == 'M':
- locs = (dates.months == self.month)
- elif freq in 'BDU':
- locs = (dates.months == self.month) & (dates.day == self.day)
- if self.base > 1:
- locs &= (locs.cumsum() % self.base == 1)
- return dates.tovalue()[locs]
-#...............................................
-class TimeSeries_QuarterLocator(TimeSeries_DateLocator):
- """Locates ticks along a Date axis, for each (multiple of) quarter.
-
-:Ivariables:
- - `base` : Integer
- Gives the spacing between two consecutive quarter ticks.
- - `month` : Integer *[1]*
- Tells on which month the ticks should be.
- - `day` : Integer *[1]*
- Tells on which day the ticks should be.
- """
-
- def __init__(self, freq, minor_locator=False,
- base=1, quarter=1, month=1, day=1):
- TimeSeries_DateLocator.__init__(self, freq, minor_locator, False,
- base, quarter, month, day)
-
- def __call__(self):
- self.verify_intervals()
- vmin, vmax = self.viewInterval.get_bounds()
- freq = self.freqstr
- if freq == 'A':
- msg = "The current frequency ('%s') is too coarse!" % freq
- raise ValueError, msg
- elif freq == 'Q':
- return range(vmin, vmax+1, self.base)
- else:
- dates = self._initialize_dates()
- values = dates.tovalue()
- if freq == 'M':
- locs = (dates.months % 4 == self.month)
- elif freq in 'BDU':
- locs = (dates.months % 4 == self.month) & (dates.day == self.day)
- if self.base > 1:
- locs &= (locs.cumsum() % self.base == 1)
- return values[locs]
-#...............................................................................
-class TimeSeries_MonthLocator(TimeSeries_DateLocator):
- """Locates ticks along a Date axis, for each (multiple of) month.
-
-:Ivariables:
- - `base` : Integer
- Gives the spacing between two consecutive quarter ticks.
- - `month` : Integer *[1]*
- Tells on which month the ticks should be.
- - `day` : Integer *[1]*
- Tells on which day the ticks should be.
- """
-
- def __init__(self, freq, minor_locator=False,
- base=1, quarter=1, month=1, day=1):
- TimeSeries_DateLocator.__init__(self, freq, minor_locator, False,
- base, quarter, month, day)
-
- def __call__(self):
- self.verify_intervals()
- vmin, vmax = self.viewInterval.get_bounds()
- freq = self.freqstr
- if freq == 'AQ':
- msg = "The current frequency ('%s') is too coarse!" % freq
- raise ValueError, msg
- elif freq == 'M':
- return range(vmin, vmax+1, self.base)
- else:
- dates = self._initialize_dates()
- values = dates.tovalue()
- if freq in 'BDU':
- locs = (dates.months == self.month) & (dates.day == self.day)
- if self.base > 1:
- locs &= (locs.cumsum() % self.base == 1)
- return values[locs]
-
#####---------------------------------------------------------------------------
#---- --- Formatter ---
#####---------------------------------------------------------------------------
class TimeSeries_DateFormatter(Formatter):
"""Formats the ticks along a DateArray axis."""
- def __init__(self, freq, fmt=None):
- if fmt is None:
- fmt = Date.default_fmtstr[freq]
- self.fmt = fmt
- self.freqstr = freq
+ def __init__(self, freq, minor_locator=False, dynamic_mode=True,):
+ self.format = None
+ self.freq = freq
+ self.locs = []
+ self.formatdict = {}
+ self.isminor = minor_locator
+ self.isdynamic = dynamic_mode
+ self.offset = 0
+ #.....
+ if freq == TS.FR_ANN:
+ self.finder = _annual_finder
+ elif freq == TS.FR_QTR:
+ self.finder = _quarterly_finder
+ elif freq == TS.FR_MTH:
+ self.finder = _monthly_finder
+ elif freq in (TS.FR_BUS, TS.FR_DAY):
+ self.finder = _daily_finder
+
+ def asminor(self):
+ "Returns the formatter set to minor mode."
+ self.isminor = True
+ return self
+ def asmajor(self):
+ "Returns the fromatter set to major mode."
+ self.isminor = False
+ return self
+
+ def _set_default_format(self, vmin, vmax):
+ "Returns the default ticks spacing."
+ self.formatdict = self.finder(vmin, vmax, self.freq, False)
+ return self.formatdict
+
+ def set_locs(self, locs):
+ 'Sets the locations of the ticks'
+ self.locs = locs
+ if len(self.locs) > 0:
+ self.verify_intervals()
+ self._set_default_format(locs[0], locs[-1])
+ #
def __call__(self, x, pos=0):
- return Date(self.freqstr, value=int(x)).strfmt(self.fmt)
+ if self.isminor:
+ fmt = self.formatdict.pop(x, '')
+ if fmt is not '':
+ retval = Date(self.freq, value=int(x)).strfmt(fmt)
+ else:
+ retval = ''
+ else:
+ retval = ''
+ return retval
+
+
#####--------------------------------------------------------------------------
#---- --- TimeSeries plots ---
#####--------------------------------------------------------------------------
@@ -514,13 +605,13 @@
assert hasattr(_series, "dates")
self._series = _series.ravel()
self.xdata = _series.dates
- self.freqstr = _series.dates.freqstr
+ self.freq = _series.dates.freq
self.xaxis.set_major_locator
else:
self._series = None
self.xdata = None
- self.freqstr = None
+ self.freq = None
self._austoscale = False
# Get the data to plot
self.legendsymbols = []
@@ -567,9 +658,9 @@
# The argument is a DateArray............
elif isinstance(a, (Date, DateArray)):
# Force to current freq
- if self.freqstr is not None:
- if a.freqstr != self.freqstr:
- a = a.asfreq(self.freqstr)
+ if self.freq is not None:
+ if a.freq != self.freq:
+ a = a.asfreq(self.freq)
# There's an argument after
if len(remaining) > 0:
#...and it's a format string
@@ -594,12 +685,9 @@
output.extend([a,b,c])
else:
output.extend([a,b])
- # continue
else:
if self.ydata is None:
raise ValueError, "No data information available!"
- #else:
- # break
# Otherwise..............................
elif len(remaining) > 0:
if isinstance(remaining[0], str):
@@ -608,20 +696,18 @@
raise ValueError, "No date information available!"
else:
output.extend([self.xdata, a, b])
- #continue
elif self.xdata is None:
raise ValueError, "No date information available!"
else:
output.extend([self.xdata, a])
- #continue
# Reinitialize the plot if needed ...........
if self.xdata is None:
self.xdata = output[0]
- self.freqstr = self.xdata.freqstr
+ self.freq = self.xdata.freq
# Force the xdata to the current frequency
- elif output[0].freqstr != self.freqstr:
+ elif output[0].freq != self.freq:
output = list(output)
- output[0] = output[0].asfreq(self.freqstr)
+ output[0] = output[0].asfreq(self.freq)
return output
#............................................
def tsplot(self,*parms,**kwargs):
@@ -631,11 +717,6 @@
parms = self._check_plot_params(*parms)
self.legendlabels.append(kwargs.get('label',None))
Subplot.plot(self, *parms,**kwargs)
- pylab.draw_if_interactive()
-# #............................................
-# def ybaseline(self,ybase,**kwargs):
-# """Plots an horizontal baseline on each subplot."""
-# self.axhline(ybase,**kwargs)
#............................................
def format_dateaxis(self,maj_spacing=None, min_spacing=None,
strformat="%Y", rotate=True):
@@ -649,49 +730,28 @@
`strformat` : String *['%Y']*
String format for major ticks ("%Y").
"""
- # Get the locator class .................
- if self.freqstr in 'BDU':
- locator = TimeSeries_DailyLocator
- self.xaxis.set_major_locator(locator(self.freqstr,
- minor_locator=False,
- dynamic_mode=True))
- self.xaxis.set_minor_locator(locator(self.freqstr,
- minor_locator=True,
- dynamic_mode=True))
- else:
- if self.freqstr == 'A':
- locator = TimeSeries_AnnualLocator
- elif self.freqstr == 'Q':
- locator = TimeSeries_QuarterlyLocator
- elif self.freqstr == 'M':
- locator = TimeSeries_MonthlyLocator
- self.xaxis.set_major_locator(locator(minor_locator=False,
- dynamic_mode=True))
- self.xaxis.set_minor_locator(locator(minor_locator=True,
- dynamic_mode=True))
+ # Get the locator class .................
+ majlocator = TimeSeries_DateLocator(self.freq, dynamic_mode=True,
+ minor_locator=False)
+ minlocator = TimeSeries_DateLocator(self.freq, dynamic_mode=True,
+ minor_locator=True)
+ self.xaxis.set_major_locator(majlocator)
+ self.xaxis.set_minor_locator(minlocator)
+ # Get the formatter .....................
+ majformatter = TimeSeries_DateFormatter(self.freq, dynamic_mode=True,
+ minor_locator=False)
+ minformatter = TimeSeries_DateFormatter(self.freq, dynamic_mode=True,
+ minor_locator=True)
+ self.xaxis.set_major_formatter(majformatter)
+ self.xaxis.set_minor_formatter(minformatter)
#........................................
- self.xaxis.set_major_formatter(TimeSeries_DateFormatter(self.freqstr))
- if rcParams['backend'] == 'PS':
- rotate = False
- warnings.warn("dateplot: PS backend detected, rotate disabled")
- if self.is_last_row():
- if rotate:
- setp(self.get_xticklabels(),rotation=45)
-# self.xaxis.set_major_formatter(FuncFormatter(self.dateticks_formatter))
-# self.xaxis.set_minor_formatter(FuncFormatter(self.dateticks_formatter))
-# else:
-# self.set_xticklabels([])
-# self.set_xlabel('')
-# #............................................
-# def plot_shifts(self,shifts,**kwargs):
-# """Plots regime shifts.
-#:param shifts: Shifts/trends to plot.
-#:type shifts: `RegimeShift`
-# """
-# self.tsplot(self.xdata,shifts.regimes,**kwargs)
-# for x in shifts.xshifts[0]:
-# self.axvline(self.xdata[x],ls=':',c='#999999',lw=0.5)
- #............................................
+# if rcParams['backend'] == 'PS':
+# rotate = False
+# warnings.warn("dateplot: PS backend detected, rotate disabled")
+# if self.is_last_row():
+# if rotate:
+# setp(self.get_xticklabels(),rotation=45)
+
TSPlot = TimeSeriesPlot
@@ -715,7 +775,6 @@
return add_generic_subplot(self, *args, **kwargs)
add_plot = add_tsplot
TSFigure = TimeSeriesFigure
-#Figure.add_tsplot =
#................................................
def tsfigure(series, **figargs):
"""Creates a new `TimeSeriesFigure` object.
@@ -728,8 +787,6 @@
"""
figargs.update(FigureClass=TSFigure)
figargs.update(series=series)
-# print "figargs:",figargs
-# num = figargs.pop('num',None)
fig = pylab.figure(**figargs)
return fig
@@ -760,16 +817,16 @@
################################################################################
if __name__ == '__main__':
- da = date_array(start_date=Date(freq='D', year=2003, quarter=3, month=1, day=17),
- length=51)
+ da = date_array(start_date=Date(freq='B', year=2003, quarter=3, month=1, day=17),
+ length=10)
ser = timeseries.time_series(MA.arange(len(da)), dates=da)
- ser[4] = MA.masked
- ser_2 = timeseries.time_series(MA.arange(len(da)), dates=da.asfreq('M'))
+# ser[4] = MA.masked
+# ser_2 = timeseries.time_series(MA.arange(len(da)), dates=da.asfreq('Q'))
pylab.figure()
pylab.gcf().add_tsplot(111)
pylab.gca().tsplot(ser, 'ko-')
pylab.gca().format_dateaxis()
- pylab.gca().tsplot(ser_2, 'rs')
+# pylab.gca().tsplot(ser_2, 'rs')
pylab.show()
\ No newline at end of file
More information about the Scipy-svn
mailing list