[Scipy-svn] r2741 - trunk/Lib/sandbox/timeseries/plotlib

scipy-svn at scipy.org scipy-svn at scipy.org
Wed Feb 21 19:43:53 EST 2007


Author: pierregm
Date: 2007-02-21 18:43:49 -0600 (Wed, 21 Feb 2007)
New Revision: 2741

Added:
   trunk/Lib/sandbox/timeseries/plotlib/mpl_timeseries_pgm.py
Log:
yet another attempt to stabilize mpl_timeseries... we're getting close!

Added: trunk/Lib/sandbox/timeseries/plotlib/mpl_timeseries_pgm.py
===================================================================
--- trunk/Lib/sandbox/timeseries/plotlib/mpl_timeseries_pgm.py	2007-02-21 21:45:00 UTC (rev 2740)
+++ trunk/Lib/sandbox/timeseries/plotlib/mpl_timeseries_pgm.py	2007-02-22 00:43:49 UTC (rev 2741)
@@ -0,0 +1,829 @@
+"""
+Classes to plot TimeSeries w/ matplotlib.
+
+: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 & Matt Knox ($Author$)"
+__version__ = '1.0'
+__revision__ = "$Revision$"
+__date__     = '$Date$'
+
+
+import matplotlib
+from matplotlib import pylab, rcParams
+from matplotlib.artist import setp
+from matplotlib.axes import Subplot, PolarSubplot
+from matplotlib.cbook import flatten
+from matplotlib.collections import LineCollection
+from matplotlib.contour import ContourSet
+from matplotlib.dates import DayLocator, MonthLocator, YearLocator, \
+                             DateFormatter
+from matplotlib.figure import Figure
+from matplotlib.legend import Legend
+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
+from timeseries import date_array, Date, DateArray, TimeSeries
+
+import warnings
+
+#####---------------------------------------------------------------------------
+#---- --- Matplotlib extensions ---
+#####---------------------------------------------------------------------------
+
+def add_generic_subplot(figure_instance, *args, **kwargs):
+    """Generalizes the `add_subplot` figure method to generic subplots.
+The specific Subplot object class to add is given through the keywords
+`SubplotClass` or `class`.
+
+:Parameters:
+    `figure_instance` : Figure object
+        Figure to which the generic subplot should be attached.
+    `args` : Misc
+        Miscellaneous arguments to the subplot.
+    `kwargs` : Dictionary
+        Keywords. Same keywords as `Subplot`, with the addition of
+        - `SubplotClass` : Type of subplot
+        - `subclass` : Shortcut to `SubplotClass`.
+        - any keyword required by the `SubplotClass` subclass.
+    """
+
+    key = figure_instance._make_key(*args, **kwargs)
+    #TODO: Find why, sometimes, key is not hashable (even if tuple)
+    # else, there's a fix below
+    try:
+        key.__hash__()
+    except TypeError:
+        key = str(key)
+    #        
+    if figure_instance._seen.has_key(key):
+        ax = figure_instance._seen[key]
+        figure_instance.sca(ax)
+        return ax
+    #
+    if not len(args): 
+        return
+#    if hasattr(args[0], '__array__'):
+#        fixedargs = args[1:]
+#    else:
+#        fixedargs = args
+    #
+    SubplotClass = kwargs.pop("SubplotClass", Subplot)
+    SubplotClass = kwargs.pop("subclass",SubplotClass)
+    if isinstance(args[0], Subplot) or isinstance(args[0], PolarSubplot):
+        a = args[0]
+        assert(a.get_figure() is figure_instance)
+#        a.set_figure(figure_instance)
+    else:
+        ispolar = kwargs.pop('polar', False)
+        if ispolar:
+            a = PolarSubplot(figure_instance, *args, **kwargs)
+        else:
+            a = SubplotClass(figure_instance, *args, **kwargs)
+            
+    figure_instance.axes.append(a)
+    figure_instance._axstack.push(a)
+    figure_instance.sca(a)
+    figure_instance._seen[key] = a
+    return a
+
+
+def nonsingular(vmin, vmax, expander=0.001, tiny=1e-15, increasing=True):
+    '''
+    Ensure the endpoints of a range are not too close together.
+
+    "too close" means the interval is smaller than 'tiny' times
+            the maximum absolute value.
+
+    If they are too close, each will be moved by the 'expander'.
+    If 'increasing' is True and vmin > vmax, they will be swapped.
+    '''
+    #TODO: Remove that when matplotlib incorporate it by default
+    swapped = False
+    if vmax < vmin:
+        vmin, vmax = vmax, vmin
+        swapped = True
+    if vmax - vmin <= max(abs(vmin), abs(vmax)) * tiny:
+        if vmin == 0.0:
+            vmin = -expander
+            vmax = expander
+        else:
+            vmin -= expander*abs(vmin)
+            vmax += expander*abs(vmax)
+    if swapped and not increasing:
+        vmin, vmax = vmax, vmin
+    return vmin, vmax
+
+##### -------------------------------------------------------------------------
+#---- --- Locators ---
+##### -------------------------------------------------------------------------
+
+def _get_default_annual_spacing(nyears):
+    """Returns a default spacing between consecutive ticks for annual data."""
+    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, 25)
+    elif nyears < 600: 
+        (min_spacing, maj_spacing) = (10, 50)
+    else:
+        factor = nyears // 1000 + 1
+        (min_spacing, maj_spacing) = (factor*20, factor*100)
+    return (min_spacing, maj_spacing)
+
+
+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 _daily_finder(locs, freqstr, aslocator):
+
+    if freqstr == 'B': 
+        periodsperyear = 261
+    elif freqstr == 'D': 
+        periodsperyear = 365
+    else: 
+        raise ValueError("unexpected frequency")
+
+    locs = N.asarray(locs)
+    (vmin, vmax) = locs[[0,-1]]
+    span = vmax - vmin + 1
+    dates = date_array(start_date=Date(freqstr,vmin), 
+                       end_date=Date(freqstr, vmax))
+    # Initialize the output
+    if aslocator:
+        default = N.arange(vmin, vmax+1) 
+    else: #asformatter
+        format = N.empty(locs.size, dtype="|S8")
+        format.flat = ''
+    # 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 year_start.size == 0:
+                if month_start.size == 0:
+                    if dates.size > 1: 
+                        idx = 1
+                    else: 
+                        idx = 0
+                    format[idx] = '%d\n%b\n%Y'
+                else:
+                    format[month_break[0]] = '%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 = (dates.day_of_week == 1)
+            year_start = period_break(dates,'year')
+            
+            week_start[0] = False
+            month_start[0] = False
+            year_start[0] = False
+
+            format[week_start] = '%d'
+            format[month_start] = '\n\n%b'
+            format[year_start] = '\n\n%b\n%Y'
+
+            if year_start.size == 0:
+                month_break = month_start.nonzero()[0]
+                if month_break.size == 0:
+                    week_break = week_start.nonzero()[0]
+                    format[week_break[0]] = '\n\n%b\n%Y'
+                else:
+                    format[month_break[0]] = '\n\n%b\n%Y'
+    # Case 3. Less than 14 months ...............
+    elif span <= 1.15 * periodsperyear:
+        month_start = period_break(dates,'month')
+        if aslocator:
+            week_start = period_break(dates, 'week')
+            minor_idx = (week_start | month_start)
+            minor_idx[0] = True
+            major = default[month_start]
+            minor = default[minor_idx]
+        else:
+            year_start = period_break(dates,'year')
+            month_start[0] = False
+            year_start[0] = False
+            format[month_start] = '%b'
+            format[year_start] = '%b\n%Y'
+            if not year_start.size:
+                format[month_break[0]] = '%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:
+        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(dates[formatted],format[formatted])])
+#...............................................................................
+def _monthly_finder(locs, freqstr, aslocator):
+    if freqstr != 'M': 
+        raise ValueError("unexpected frequency")
+    periodsperyear = 12
+    locs = N.asarray(locs)
+    (vmin, vmax) = locs[[0,-1]]    
+    (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 = ''
+    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 year_start.size:
+                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(locs, freqstr, aslocator):
+    if freqstr != 'Q': 
+        raise ValueError("unexpected frequency")
+    periodsperyear = 4
+    locs = N.asarray(locs)
+    (vmin, vmax) = locs[[0,-1]]    
+    (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 = ''
+    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 year_start.size:
+                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:
+            print "major_idx",major_idx
+            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(locs, freqstr, aslocator):
+    if freqstr != 'Q': 
+        raise ValueError("unexpected frequency")
+    locs = N.asarray(locs)
+    (vmin, vmax) = locs[[0,-1]]    
+    (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.base = base
+        (self.quarter, self.month, self.day) = (quarter, month, day)
+        self.isminor = minor_locator
+        self.isdynamic = dynamic_mode
+        self.offset = 0
+        #.....
+        if freq == 'A':
+            self.finder = _annual_finder
+        elif freq == 'Q':
+            self.finder = _quarterly_finder
+        elif freq == 'M':
+            self.finder = _monthly_finder
+        elif freq == 'D':
+            self.finder = _daily_finder
+            
+    def asminor(self):
+        "Returns the locator set to minor mode."
+        self.isminor = True
+        return self
+    
+    def asmajor(self):
+        "Returns the locator set to major mode."
+        self.isminor = False
+        return self
+    
+    def _get_default_locs(self, vmin, vmax):
+        "Returns the default locations of ticks."
+        (minor, major) = self.finder(N.arange(vmin, vmax+1), self.freqstr, True)
+        if self.isminor:
+            return minor
+        return major
+    
+    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:
+            locs = self._get_default_locs(vmin, vmax)
+        else:
+            base = self.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.
+        """
+        self.verify_intervals()
+        dmin, dmax = self.dataInterval.get_bounds()
+        locs = self._get_default_locs(dmin, dmax)
+        (vmin, vmax) = locs[[0, -1]]
+        if vmin == vmax:
+            vmin -= 1
+            vmax += 1
+        return nonsingular(vmin, vmax)      
+
+#####---------------------------------------------------------------------------
+#---- --- Formatter ---
+#####---------------------------------------------------------------------------            
+class TimeSeries_DateFormatter(Formatter):
+    """Formats the ticks along a DateArray axis."""
+    
+    def __init__(self, freq, minor_locator=False, dynamic_mode=True,):
+        self.format = None
+        self.freqstr = freq
+        self.locs = []
+        self.formatdict = {}
+        self.isminor = minor_locator
+        self.isdynamic = dynamic_mode
+        self.offset = 0
+        #.....
+        if freq == 'A':
+            self.finder = _annual_finder
+        elif freq == 'Q':
+            self.finder = _quarterly_finder
+        elif freq == 'M':
+            self.finder = _monthly_finder
+        elif freq == 'D':
+            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(self.locs, self.freqstr, 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):
+        if self.isminor:
+            fmt = self.formatdict.pop(x, '')
+            if fmt is not '':
+                retval = Date(self.freqstr, value=int(x)).strfmt(fmt)
+            else:
+                retval = ''
+        else:
+            retval = ''
+        return retval
+    
+
+
+
+#####--------------------------------------------------------------------------
+#---- --- TimeSeries plots ---
+#####--------------------------------------------------------------------------
+class TimeSeriesPlot(Subplot, object):
+    """Defines a time series based subclass of Subplot."""
+    def __init__(self, fig=None, *args, **kwargs):
+        """
+Accepts the same keywords as a standard subplot, plus a specific `series` keyword.
+
+:Parameters:
+    `fig` : Figure
+        Base figure.
+        
+:Keywords:
+    `series` : TimeSeries
+        Data to plot
+        
+        """
+        # Retrieve the series ...................
+        _series = kwargs.pop('series',None)
+        Subplot.__init__(self,fig,*args,**kwargs)
+#        # Force fig to be defined .....
+#        if fig is None:
+#            fig = TSFigure(_series)
+        # Process options .......................
+        if _series is not None:
+            assert hasattr(_series, "dates")
+            self._series = _series.ravel()
+            self.xdata = _series.dates
+            self.freqstr = _series.dates.freqstr
+            self.xaxis.set_major_locator
+            
+        else:
+            self._series = None
+            self.xdata = None
+            self.freqstr = None
+        self._austoscale = False
+        # Get the data to plot 
+        self.legendsymbols = []
+        self.legendlabels = []
+    #............................................
+    def set_ydata(self, series=None):
+        """Sets the base time series."""
+        if self._series is not None:
+            print "WARNING ! Base series is being changed."""
+        self._series = series.ravel()
+        if isinstance(series, TimeSeries):
+            self.xdata = self.series.dates
+    #....
+    def get_ydata(self):
+        """Gets the base time series."""
+        return self._series
+    ydata = property(fget=get_ydata, fset=set_ydata, doc='Time series')
+    #............................................    
+    def _check_plot_params(self,*args):
+        """Defines the plot coordinates (and basic plotting arguments)."""
+        remaining = list(args)
+        # No args ? Use defaults, if any
+        if len(args) == 0:
+            if self.xdata is None:
+                raise ValueError, "No date information available!"
+            return (self.xdata, self.ydata)
+        output = []
+        while len(remaining) > 0:
+            a = remaining.pop(0)
+            # The argument is a format: use default dates/
+            if isinstance(a,str):
+                if self.xdata is None:
+                    raise ValueError, "No date information available!"
+                else:
+                    output.extend([self.xdata, self.ydata, a])
+            # The argument is a TimeSeries: use its dates for x
+            elif isinstance(a, TimeSeries):
+                (x,y) = (a._dates, a._series)
+                if len(remaining) > 0 and isinstance(remaining[0], str):
+                    b = remaining.pop(0)
+                    output.extend([x,y,b])
+                else:
+                    output.extend([x,y])
+            # 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)
+                # There's an argument after
+                if len(remaining) > 0:
+                    #...and it's a format string
+                    if isinstance(remaining[0], str):
+                        b = remaining.pop(0)
+                        if self.ydata is None:
+                            raise ValueError, "No data information available!"
+                        else:
+                            output.extend([a, self.ydata, b])
+                    #... and it's another date: use the default
+                    elif isinstance(remaining[0], DateArray):
+                        if self.ydata is None:
+                            raise ValueError, "No data information available!"
+                        else:
+                            output.extend([a, self.ydata])
+                    #... and it must be some data
+                    else:   
+                        b = remaining.pop(0)
+                        if len(remaining) > 0:
+                            if isinstance(remaining[0], str):
+                                c = remaining.pop(0)
+                                output.extend([a,b,c])
+                            else:
+                                output.extend([a,b])
+                else:
+                    if self.ydata is None:
+                        raise ValueError, "No data information available!"
+            # Otherwise..............................
+            elif len(remaining) > 0:
+                if isinstance(remaining[0], str):
+                    b = remaining.pop(0)
+                    if self.xdata is None:
+                        raise ValueError, "No date information available!"
+                    else:
+                        output.extend([self.xdata, a, b])
+                elif self.xdata is None:
+                    raise ValueError, "No date information available!"
+                else:
+                    output.extend([self.xdata, a])
+        # Reinitialize the plot if needed ...........
+        if self.xdata is None:
+            self.xdata = output[0]
+            self.freqstr = self.xdata.freqstr
+        # Force the xdata to the current frequency
+        elif output[0].freqstr != self.freqstr:
+            output = list(output)
+            output[0] = output[0].asfreq(self.freqstr)
+        return output
+    #............................................
+    def tsplot(self,*parms,**kwargs):
+        """Plots the data parsed in argument.
+This command accepts the same keywords as `matplotlib.plot`."""
+        #print "Parameters: %s - %i" % (parms, len(parms))
+        parms = self._check_plot_params(*parms)
+        self.legendlabels.append(kwargs.get('label',None))
+        Subplot.plot(self, *parms,**kwargs)
+    #............................................       
+    def format_dateaxis(self,maj_spacing=None, min_spacing=None, 
+                        strformat="%Y", rotate=True):
+        """Pretty-formats the date axis (x-axis).
+        
+:Parameters:
+    `major` : Integer *[5]* 
+        Major tick locator, in years (major tick every `major` years).
+    `minor` : Integer *[12]* 
+        Minor tick locator, in months (minor ticks every `minor` months).
+    `strformat` : String *['%Y']*
+        String format for major ticks ("%Y").
+        """
+        # Get the locator class ................. 
+        majlocator = TimeSeries_DateLocator(self.freqstr, dynamic_mode=True,
+                                            minor_locator=False)
+        minlocator = TimeSeries_DateLocator(self.freqstr, 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.freqstr, dynamic_mode=True,
+                                                minor_locator=False)
+        minformatter = TimeSeries_DateFormatter(self.freqstr, dynamic_mode=True,
+                                                minor_locator=True)
+        self.xaxis.set_major_formatter(majformatter)
+        self.xaxis.set_minor_formatter(minformatter)
+        #........................................
+#        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
+
+
+#####--------------------------------------------------------------------------
+#---- --- TimeSeries Figures ---
+#####--------------------------------------------------------------------------        
+class TimeSeriesFigure(Figure):
+    """Time Series Figure: all subplots share the same time series.
+    """
+    def __init__(self, series=None, **kwargs):
+        self._series = series
+        Figure.__init__(self,**kwargs)
+        fspnum = kwargs.pop('fspnum',None)
+        if fspnum is not None:
+            self.add_tsplot(fspnum, series=series)
+    #.........
+    def add_tsplot(self, *args, **kwargs):
+        """Adds a `TimeSeriesPlot` subplot to the figure."""
+        kwargs.update(SubplotClass=TimeSeriesPlot,
+                      series=self._series)        
+        return add_generic_subplot(self, *args, **kwargs)
+    add_plot = add_tsplot
+TSFigure = TimeSeriesFigure
+#................................................
+def tsfigure(series, **figargs):    
+    """Creates a new `TimeSeriesFigure` object.
+    
+:Parameters:
+    `series` : TimeSeries object
+        Input data.
+    `figargs` : Dictionary
+        Figure options [`figsize`, `dpi`, `facecolor`, `edgecolor`, `frameon`].
+    """
+    figargs.update(FigureClass=TSFigure)
+    figargs.update(series=series)
+    fig = pylab.figure(**figargs)
+    return fig
+
+def add_tsplot(axes, *args, **kwargs):
+    kwargs.update(SubplotClass=TimeSeriesPlot)
+    if 'series' not in kwargs.keys():
+        kwargs['series'] = None
+    return add_generic_subplot(axes, *args, **kwargs)
+Figure.add_tsplot = add_tsplot
+    
+
+def tsplot(*args, **kwargs):
+    # allow callers to override the hold state by passing hold=True|False
+    b = pylab.ishold()
+    h = kwargs.pop('hold', None)
+    if h is not None:
+        pylab.hold(h)
+    try:
+        ret =  pylab.gca().add_tsplot(*args, **kwargs)
+        pylab.draw_if_interactive()
+    except:
+        pylab.hold(b)
+        raise
+
+    pylab.hold(b)
+    return ret
+
+################################################################################
+if __name__ == '__main__':
+
+    da = date_array(start_date=Date(freq='M', year=2003, quarter=3, month=1, day=17), 
+                    length=51)
+    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('Q'))
+    
+    pylab.figure()
+    pylab.gcf().add_tsplot(111)
+    pylab.gca().tsplot(ser, 'ko-')
+    pylab.gca().format_dateaxis()
+#    pylab.gca().tsplot(ser_2, 'rs')
+    pylab.show()
+    
\ No newline at end of file


Property changes on: trunk/Lib/sandbox/timeseries/plotlib/mpl_timeseries_pgm.py
___________________________________________________________________
Name: svn:keywords
   + Date 
Author 
Revision
Id




More information about the Scipy-svn mailing list