[Scipy-svn] r2808 - trunk/Lib/sandbox/timeseries

scipy-svn at scipy.org scipy-svn at scipy.org
Fri Mar 2 03:48:46 EST 2007


Author: pierregm
Date: 2007-03-02 02:48:36 -0600 (Fri, 02 Mar 2007)
New Revision: 2808

Removed:
   trunk/Lib/sandbox/timeseries/extras.py
   trunk/Lib/sandbox/timeseries/tdates.py
Log:
extras : deleted, redispatched to addons/filters and addons/interpolate

Deleted: trunk/Lib/sandbox/timeseries/extras.py
===================================================================
--- trunk/Lib/sandbox/timeseries/extras.py	2007-03-02 08:48:04 UTC (rev 2807)
+++ trunk/Lib/sandbox/timeseries/extras.py	2007-03-02 08:48:36 UTC (rev 2808)
@@ -1,148 +0,0 @@
-"""Time Series add-ons.
-
-A collection of utilities for timeseries
-
-:author: Pierre GF Gerard-Marchant & Matt Knox
-:contact: pierregm_at_uga_dot_edu - mattknox_ca_at_hotmail_dot_com
-:version: $Id$
-"""
-__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author$)"
-__version__ = '1.0'
-__revision__ = "$Revision$"
-__date__     = '$Date$'
-
-__all__ = [
-    'forward_fill', 'backward_fill', 'interp_masked1d',
-    'expmave'
-          ]
-
-import numpy as N
-from scipy.interpolate import fitpack
-import maskedarray as MA
-from maskedarray import masked, nomask, getmask, MaskedArray
-import numpy.core.numeric as numeric
-
-#####---------------------------------------------------------------------------
-#---- --- Functions for filling in masked values in a masked array ---
-#####---------------------------------------------------------------------------
-
-def forward_fill(marr, maxgap=None):
-    """forward_fill(marr, maxgap=None)
-
-Forward fill masked values in a 1-d array when there are <= maxgap
-consecutive masked values. If maxgap is None, then forward fill all
-masked values."""
-
-    if numeric.ndim(marr) > 1:
-        raise ValueError,"The input array should be 1D only!"
-
-    marr = MA.array(marr, copy=True)
-    if getmask(marr) is nomask or marr.size == 0:
-        return marr
-
-    currGap = 0
-
-    if maxgap is not None:
-        for i in range(1, marr.size):
-            if marr._mask[i]:
-                currGap += 1
-                if currGap <= maxgap and not marr._mask[i-1]:
-                    marr._data[i] = marr._data[i-1]
-                    marr._mask[i] = False
-                elif currGap == maxgap + 1:
-                    marr._mask[i-maxgap:i] = True
-            else:
-                currGap = 0               
-    else:
-        for i in range(1, marr.size):
-            if marr._mask[i] and not marr._mask[i-1]:
-                marr._data[i] = marr._data[i-1]
-                marr._mask[i] = False
-    return marr
-
-
-def backward_fill(marr, maxgap=None):
-    """backward_fill(marr, maxgap=None)
-
-backward fill masked values in a 1-d array when there are <= maxgap
-consecutive masked values. If maxgap is None, then backward fill all
-masked values."""
-    return forward_fill(marr[::-1], maxgap=maxgap)[::-1]
-    
-
-def interp_masked1d(marr, kind='linear'):
-    """interp_masked1d(marr, king='linear')
-
-Interpolate masked values in marr according to method kind.
-kind must be one of 'constant', 'linear', 'cubic', quintic'
-"""
-    if numeric.ndim(marr) > 1: 
-        raise ValueError("array must be 1 dimensional!")
-    #
-    marr = MA.array(marr, copy=True)
-    if getmask(marr) is nomask: 
-        return marr
-    #
-    unmaskedIndices = (~marr._mask).nonzero()[0]
-    if unmaskedIndices.size < 2: 
-        return marr
-    #    
-    kind = kind.lower()
-    if kind == 'constant': 
-        return forward_fill(marr)
-    try:
-        k = {'linear' : 1,
-             'cubic' : 3,
-             'quintic' : 5}[kind.lower()]
-    except KeyError:
-        raise ValueError("Unsupported interpolation type.")
-    
-    first_unmasked, last_unmasked = MA.extras.flatnotmasked_edges(marr)
-    
-    vals = marr.data[unmaskedIndices]
-    
-    tck = fitpack.splrep(unmaskedIndices, vals, k=k)
-    
-    maskedIndices = marr._mask.nonzero()[0]
-    interpIndices = maskedIndices[(maskedIndices > first_unmasked) & \
-                                  (maskedIndices < last_unmasked)]
-    marr[interpIndices] = fitpack.splev(interpIndices, tck).astype(marr.dtype)
-    return marr
-
-
-#####---------------------------------------------------------------------------
-#---- --- Moving average functions                                           ---
-#####---------------------------------------------------------------------------
-
-def expmave(data, n, tol=1e-6):
-    """calculate exponential moving average of a series.
-
-:Parameters:
-    - `data` (ndarray, MaskedArray) : data is a valid ndarray or MaskedArray
-      or an instance of a subclass of these types. In particular, TimeSeries
-      objects are valid here.
-    - `n` (int) : time periods. Where the smoothing factor is 2/(n + 1)
-    - `tol` (float, *[1e-6]*) : when `data` contains masked values, this
-      parameter will determine what points in the result should be masked.
-      Values in the result that would not be "significantly" impacted (as
-      determined by this parameter) by the masked values are left unmasked.
-"""
-    if isinstance(data, MaskedArray):
-        ismasked = (data._mask is not nomask)
-    else:
-        ismasked = False
-        
-    k = 2./float(n + 1)
-    def expmave_sub(a, b):
-        return b + k * (a - b)
-        
-    if ismasked:
-        data = data.filled(0)
-
-    result = N.frompyfunc(expmave_sub, 2, 1).accumulate(data).astype(data.dtype)
-    if ismasked:
-        _unmasked = N.logical_not(MA.getmask(data)).astype(N.float_)
-        marker = 1 - N.frompyfunc(expmave_sub, 2, 1).accumulate(_unmasked)
-        result[marker > tol] = masked
-
-    return result

Deleted: trunk/Lib/sandbox/timeseries/tdates.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tdates.py	2007-03-02 08:48:04 UTC (rev 2807)
+++ trunk/Lib/sandbox/timeseries/tdates.py	2007-03-02 08:48:36 UTC (rev 2808)
@@ -1,1064 +0,0 @@
-"""
-Classes definition for the support of individual dates and array of dates.
-
-:author: Pierre GF Gerard-Marchant & Matt Knox
-:contact: pierregm_at_uga_dot_edu - mattknox_ca_at_hotmail_dot_com
-:version: $Id$
-"""
-__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author$)"
-__version__ = '1.0'
-__revision__ = "$Revision$"
-__date__     = '$Date$'
-
-import datetime as dt
-
-import itertools
-import warnings
-import types
-
-
-import numpy
-from numpy import bool_, float_, int_, object_
-from numpy import ndarray
-import numpy.core.numeric as numeric
-import numpy.core.fromnumeric as fromnumeric
-import numpy.core.numerictypes as ntypes
-from numpy.core.numerictypes import generic
-
-import maskedarray as MA
-
-try:
-    from mx.DateTime import DateTimeType
-except ImportError:
-    class DateTimeType: pass
-
-from parser import DateFromString, DateTimeFromString    
-
-import tcore as corelib
-import cseries
-
-
-
-__all__ = [
-'Date', 'DateArray','isDate','isDateArray',
-'DateError', 'ArithmeticDateError', 'FrequencyDateError','InsufficientDateError',
-'datearray','date_array', 'date_array_fromlist', 'date_array_fromrange',
-'day_of_week','day_of_year','day','month','quarter','year','hour','minute','second',
-'truncateDate','monthToQuarter','thisday','today','prevbusday','asfreq',
-'period_break'
-           ]
-
-
-#####---------------------------------------------------------------------------
-#---- --- Date Info ---
-#####---------------------------------------------------------------------------
-
-OriginDate = dt.datetime(1970, 1, 1)
-secondlyOriginDate = OriginDate - dt.timedelta(seconds=1)
-minutelyOriginDate = OriginDate - dt.timedelta(minutes=1)
-hourlyOriginDate = OriginDate - dt.timedelta(hours=1)
-
-
-#####---------------------------------------------------------------------------
-#---- --- Date Exceptions ---
-#####---------------------------------------------------------------------------
-class DateError(Exception):
-    """Defines a generic DateArrayError."""
-    def __init__ (self, args=None):
-        "Create an exception"
-        Exception.__init__(self)
-        self.args = args
-    def __str__(self):
-        "Calculate the string representation"
-        return str(self.args)
-    __repr__ = __str__
-    
-class InsufficientDateError(DateError):
-    """Defines the exception raised when there is not enough information 
-    to create a Date object."""
-    def __init__(self, msg=None):
-        if msg is None:
-            msg = "Insufficient parameters given to create a date at the given frequency"
-        DateError.__init__(self, msg)
-        
-class FrequencyDateError(DateError):
-    """Defines the exception raised when the frequencies are incompatible."""
-    def __init__(self, msg, freql=None, freqr=None):
-        msg += " : Incompatible frequencies!"
-        if not (freql is None or freqr is None):
-            msg += " (%s<>%s)" % (freql, freqr)
-        DateError.__init__(self, msg)
-        
-class ArithmeticDateError(DateError):
-    """Defines the exception raised when dates are used in arithmetic expressions."""
-    def __init__(self, msg=''):
-        msg += " Cannot use dates for arithmetics!"
-        DateError.__init__(self, msg)
-
-#####---------------------------------------------------------------------------
-#---- --- Date Class ---
-#####---------------------------------------------------------------------------
-
-class Date:
-    """Defines a Date object, as the combination of a date and a frequency.
-    Several options are available to construct a Date object explicitly:
-
-    - Give appropriate values to the `year`, `month`, `day`, `quarter`, `hours`, 
-      `minutes`, `seconds` arguments.
-      
-      >>> td.Date(freq='Q',year=2004,quarter=3)
-      >>> td.Date(freq='D',year=2001,month=1,day=1)
-      
-    - Use the `string` keyword. This method calls the `mx.DateTime.Parser`
-      submodule, more information is available in its documentation.
-      
-      >>> ts.Date('D', '2007-01-01')
-      
-    - Use the `datetime` keyword with an existing datetime.datetime object.
-
-      >>> td.Date('D', datetime=datetime.datetime.now())
-      """
-    default_fmtstr = {'A': "%Y",
-                      'Q': "%YQ%q",
-                      'M': "%b-%Y",
-                      'W': "%d-%b-%Y",
-                      'B': "%d-%b-%Y",
-                      'D': "%d-%b-%Y",
-                      'U': "%d-%b-%Y",
-                      'H': "%d-%b-%Y %H:00",
-                      'T': "%d-%b-%Y %H:%M",
-                      'S': "%d-%b-%Y %H:%M:%S"
-                      }
-      
-    def __init__(self, freq, value=None, string=None,
-                 year=None, month=None, day=None, quarter=None, 
-                 hour=None, minute=None, second=None, 
-                 datetime=None):
-        
-        if hasattr(freq, 'freq'):
-            self.freq = corelib.check_freq(freq.freq)
-        else:
-            self.freq = corelib.check_freq(freq)
-        self.freqstr = corelib.freq_tostr(self.freq)
-        
-        
-        if value is not None:
-            if isinstance(value, ndarray):
-                value = int(value)
-        
-            if isinstance(value, str):
-                if self.freqstr in ('H', 'T', 'S'):
-                    self.datetime = DateTimeFromString(value)
-                else:
-                    self.datetime = DateFromString(value)
-            elif self.freqstr == 'A':
-                self.datetime = dt.datetime(value, 1, 1)
-            elif self.freqstr == 'B':
-                valtmp = (value - 1)//5
-                self.datetime = dt.datetime.fromordinal(value + valtmp*2)
-            elif self.freqstr in ['D','U']:
-                self.datetime = dt.datetime.fromordinal(value)
-            elif self.freqstr == 'H':
-                self.datetime = hourlyOriginDate + dt.timedelta(hours=value)
-            elif self.freqstr == 'M':
-                year = (value - 1)//12 + 1
-                month = value - (year - 1)*12
-                self.datetime = dt.datetime(year, month, 1)
-            elif self.freqstr == 'Q':
-                year = (value - 1)//4 + 1
-                month = (value - (year - 1)*4)*3
-                self.datetime = dt.datetime(year, month, 1)
-            elif self.freqstr == 'S':
-                self.datetime = secondlyOriginDate + dt.timedelta(seconds=value)
-            elif self.freqstr == 'T':
-                self.datetime = minutelyOriginDate + dt.timedelta(minutes=value)
-            elif self.freqstr == 'W':
-                self.datetime = dt.datetime(1,1,7) + \
-                                dt.timedelta(days=(value-1)*7)
-        
-        elif string is not None:
-            if self.freqstr in ('H', 'T', 'S'):
-                self.datetime = DateTimeFromString(string)
-            else:
-                self.datetime = DateFromString(string)
-            
-        elif datetime is not None:
-            if isinstance(datetime, DateTimeType):
-                datetime = mx_to_datetime(datetime)
-            self.datetime = truncateDate(self.freq, datetime)
-            
-        else:
-            # First, some basic checks.....
-            if year is None:
-                raise InsufficientDateError            
-            if self.freqstr in 'BDWU':
-                if month is None or day is None: 
-                    raise InsufficientDateError
-            elif self.freqstr == 'M':
-                if month is None: 
-                    raise InsufficientDateError
-                day = 1
-            elif self.freqstr == 'Q':
-                if quarter is None: 
-                    raise InsufficientDateError
-                month = quarter * 3
-                day = 1
-            elif self.freqstr == 'A':
-                month = 1
-                day = 1
-            elif self.freqstr == 'S':
-                if month is None or day is None or second is None: 
-                    raise InsufficientDateError
-                
-            if self.freqstr in ['A','B','D','M','Q','W']:
-                self.datetime = truncateDate(self.freq, dt.datetime(year, month, day))
-                if self.freqstr == 'B':
-                    if self.datetime.isoweekday() in [6,7]:
-                        raise ValueError("Weekend passed as business day")
-            elif self.freqstr in 'HTS':
-                if hour is None:
-                    if minute is None:
-                        if second is None:
-                            hour = 0
-                        else:
-                            hour = second//3600
-                    else:
-                        hour = minute // 60
-                if minute is None:
-                    if second is None:
-                        minute = 0
-                    else:
-                        minute = (second-hour*3600)//60
-                if second is None:
-                    second = 0
-                else:
-                    second = second % 60
-                self.datetime = truncateDate(self.freqstr,
-                                             dt.datetime(year, month, day, 
-                                                         hour, minute, second))
-        self.value = self.__value()
-
-    def __getitem__(self, indx):
-        return self
-
-    @property
-    def day(self):          
-        "Returns the day of month."
-        return self.__getdateinfo__('D')
-    @property
-    def day_of_week(self):  
-        "Returns the day of week."
-        return self.__getdateinfo__('W')
-    @property
-    def day_of_year(self):  
-        "Returns the day of year."
-        return self.__getdateinfo__('R')
-    @property
-    def month(self):        
-        "Returns the month."
-        return self.__getdateinfo__('M')
-    @property
-    def quarter(self):   
-        "Returns the quarter."   
-        return self.__getdateinfo__('Q')
-    @property
-    def year(self):         
-        "Returns the year."
-        return self.__getdateinfo__('Y')
-    @property
-    def second(self):    
-        "Returns the seconds."  
-        return self.__getdateinfo__('S')
-    @property
-    def minute(self):     
-        "Returns the minutes."  
-        return self.__getdateinfo__('T')
-    @property
-    def hour(self):         
-        "Returns the hour."
-        return self.__getdateinfo__('H')
-    @property
-    def week(self):
-        "Returns the week."
-        return self.__getdateinfo__('I')
-        
-    def __getdateinfo__(self, info):
-        return int(cseries.getDateInfo(numpy.asarray(self.value), 
-                                       self.freq, info))
-    __getDateInfo = __getdateinfo__
- 
-    def __add__(self, other):
-        if isinstance(other, Date):
-            raise FrequencyDateError("Cannot add dates", 
-                                     self.freqstr, other.freqstr)
-        return Date(freq=self.freq, value=int(self) + other)
-    
-    def __radd__(self, other): 
-        return self+other
-    
-    def __sub__(self, other):
-        if isinstance(other, Date):
-            if self.freq != other.freq:
-                raise FrequencyDateError("Cannot subtract dates", \
-                                         self.freqstr, other.freqstr)
-            else:
-                return int(self) - int(other) 
-        else:
-            return self + (-1) * int(other)
-    
-    def __eq__(self, other):
-        if not hasattr(other, 'freq'):
-            return False
-        elif self.freq != other.freq:
-            raise FrequencyDateError("Cannot compare dates", \
-                                     self.freqstr, other.freqstr)
-        return int(self) == int(other) 
-    
-    def __cmp__(self, other): 
-        if not hasattr(other, 'freq'):
-            return False
-        elif self.freq != other.freq:
-            raise FrequencyDateError("Cannot compare dates", \
-                                     self.freqstr, other.freqstr)
-        return int(self)-int(other)    
-        
-    def __hash__(self): 
-        return hash(int(self)) ^ hash(self.freq)
-    
-    def __int__(self):
-        return self.value
-    
-    def __float__(self):
-        return float(self.value)
-    
-    def __value(self):   
-        "Converts the date to an integer, depending on the current frequency."
-        # Annual .......
-        if self.freqstr == 'A':
-            val = self.datetime.year
-        # Quarterly.....
-        elif self.freqstr == 'Q':
-            val = (self.datetime.year-1)*4 + self.datetime.month//3
-        # Monthly.......
-        elif self.freqstr == 'M':
-            val = (self.datetime.year-1)*12 + self.datetime.month
-        # Weekly........
-        elif self.freqstr == 'W':
-            val = self.datetime.toordinal()//7
-        # Business days.
-        elif self.freqstr == 'B':
-            days = self.datetime.toordinal()
-            weeks = days // 7
-            val = days - weeks*2  
-        # Daily/undefined
-        elif self.freqstr in 'DU':
-            val = self.datetime.toordinal()
-        # Hourly........
-        elif self.freqstr == 'H':
-            delta = (self.datetime - hourlyOriginDate)
-            val = delta.days*24 + delta.seconds/(3600)
-        # Minutely......
-        elif self.freqstr == 'T':
-            delta = (self.datetime - minutelyOriginDate)
-            val = delta.days*1440 + delta.seconds/(60)
-        # Secondly......
-        elif self.freqstr == 'S':
-            delta = (self.datetime - secondlyOriginDate)
-            val = delta.days*86400 + delta.seconds
-        return int(val)
-    #......................................................        
-    def strfmt(self, fmt):
-        "Formats the date"
-        if fmt is None:
-            fmt = self.default_fmtstr[self.freqstr]
-        return cseries.strfmt(self.datetime, fmt)
-            
-    def __str__(self):
-        return self.strfmt(self.default_fmtstr[self.freqstr])
-
-    def __repr__(self): 
-        return "<%s : %s>" % (str(self.freqstr), str(self))
-    #......................................................
-    def toordinal(self):
-        "Returns the date as an ordinal."
-        return self.datetime.toordinal()
-
-    def fromordinal(self, ordinal):
-        "Returns the date as an ordinal."
-        return Date(self.freq, datetime=dt.datetime.fromordinal(ordinal))
-    
-    def tostring(self):
-        "Returns the date as a string."
-        return str(self)
-    
-    def toobject(self):
-        "Returns the date as itself."
-        return self
-    
-    def isvalid(self):
-        "Returns whether the DateArray is valid: no missing/duplicated dates."
-        # A date is always valid by itself, but we need the object to support the function
-        # when we're working with singletons.
-        return True
-    #......................................................
-        
-    
-#####---------------------------------------------------------------------------
-#---- --- Functions ---
-#####---------------------------------------------------------------------------
-
-def mx_to_datetime(mxDate):
-    microsecond = 1000000*(mxDate.second % 1)
-    return dt.datetime(mxDate.year, mxDate.month,
-                       mxDate.day, mxDate.hour,
-                       mxDate.minute,
-                       int(mxDate.second), microsecond)
-
-
-def truncateDate(freq, datetime):
-    "Chops off the irrelevant information from the datetime object passed in."
-    freqstr = corelib.check_freqstr(freq)
-    if freqstr == 'A':
-        return dt.datetime(datetime.year, 1, 1)
-    elif freqstr == 'Q':
-        return dt.datetime(datetime.year, monthToQuarter(datetime.month)*3, 1)
-    elif freqstr == 'M':
-        return dt.datetime(datetime.year, datetime.month, 1)
-    elif freqstr == 'W':
-        d = datetime.toordinal()
-        return dt.datetime.fromordinal(d + (7 - d % 7) % 7)
-    elif freqstr in 'BD':
-        if freq == 'B' and datetime.isoweekday() in (6,7):
-            raise ValueError("Weekend passed as business day")
-        return dt.datetime(datetime.year, datetime.month, datetime.day)
-    elif freqstr == 'H':
-        return dt.datetime(datetime.year, datetime.month, datetime.day, \
-                           datetime.hour)
-    elif freqstr == 'T':
-        return dt.datetime(datetime.year, datetime.month, datetime.day, \
-                           datetime.hour, datetime.minute)
-    else:
-        return datetime
-    
-def monthToQuarter(monthNum):
-    """Returns the quarter corresponding to the month `monthnum`.
-    For example, December is the 4th quarter, Januray the first."""
-    return int((monthNum-1)/3)+1
-
-def thisday(freq):
-    "Returns today's date, at the given frequency `freq`."
-    freqstr = corelib.check_freqstr(freq)
-    tempDate = dt.datetime.now()
-    # if it is Saturday or Sunday currently, freq==B, then we want to use Friday
-    if freqstr == 'B' and tempDate.isoweekday() >= 6:
-        tempDate = tempDate - dt.timedelta(days=(tempDate.isoweekday() - 5))
-    if freqstr in ('B','D','H','S','T','W','U'):
-        return Date(freq, datetime=tempDate)
-    elif freqstr == 'M':
-        return Date(freq, year=tempDate.year, month=tempDate.month)
-    elif freqstr == 'Q':
-        return Date(freq, year=tempDate.year, quarter=monthToQuarter(tempDate.month))
-    elif freqstr == 'A':
-        return Date(freq, year=tempDate.year)
-today = thisday
-
-def prevbusday(day_end_hour=18, day_end_min=0):
-    "Returns the previous business day."
-    tempDate = dt.datetime.now()
-    dateNum = tempDate.hour + float(tempDate.minute)/60
-    checkNum = day_end_hour + float(day_end_min)/60
-    if dateNum < checkNum: 
-        return thisday('B') - 1
-    else: 
-        return thisday('B')
-                
-def asfreq(date, toFreq, relation="BEFORE"):
-    """Returns a date converted to another frequency `toFreq`, according to the
-    relation `relation` ."""
-    tofreq = corelib.check_freq(toFreq)
-    _rel = relation.upper()[0]
-    if _rel not in ['B', 'A']:
-        msg = "Invalid relation '%s': Should be in ['before', 'after']"
-        raise ValueError, msg % relation
-
-    if not isinstance(date, Date):
-        raise DateError, "Date should be a valid Date instance!"
-
-    if date.freqstr == 'U':
-        warnings.warn("Undefined frequency: assuming daily!")
-        fromfreq = corelib.freq_revdict['D']
-    else:
-        fromfreq = date.freq
-    
-    if fromfreq == tofreq:
-        return date
-    else:
-        value = cseries.asfreq(numeric.asarray(date.value), fromfreq, tofreq, _rel)
-        if value > 0:
-            return Date(freq=tofreq, value=value)
-        else:
-            return None
-Date.asfreq = asfreq
-            
-def isDate(data):
-    "Returns whether `data` is an instance of Date."
-    return isinstance(data, Date) or \
-           (hasattr(data,'freq') and hasattr(data,'value'))
-
-            
-#####---------------------------------------------------------------------------
-#---- --- DateArray ---
-#####--------------------------------------------------------------------------- 
-ufunc_dateOK = ['add','subtract',
-                'equal','not_equal','less','less_equal', 'greater','greater_equal',
-                'isnan']
-
-class _datearithmetics(object):
-    """Defines a wrapper for arithmetic methods.
-Instead of directly calling a ufunc, the corresponding method of  the `array._data` 
-object is called instead.
-If `asdates` is True, a DateArray object is returned , else a regular ndarray
-is returned.
-    """
-    def __init__ (self, methodname, asdates=True):
-        """
-:Parameters:
-    - `methodname` (String) : Method name.
-        """
-        self.methodname = methodname
-        self._asdates = asdates
-        self.__doc__ = getattr(methodname, '__doc__')
-        self.obj = None
-    #
-    def __get__(self, obj, objtype=None):
-        self.obj = obj
-        return self
-    #
-    def __call__ (self, other, *args, **kwargs):
-        "Execute the call behavior."
-        instance = self.obj
-        freq = instance.freq
-        if 'context' not in kwargs:
-            kwargs['context'] = 'DateOK'
-        method = getattr(super(DateArray,instance), self.methodname)
-        if isinstance(other, DateArray):
-            if other.freq != freq:
-                raise FrequencyDateError("Cannot operate on dates", \
-                                         freq, other.freq)
-        elif isinstance(other, Date):
-            if other.freq != freq:
-                raise FrequencyDateError("Cannot operate on dates", \
-                                         freq, other.freq)
-            other = other.value
-        elif isinstance(other, ndarray):
-            if other.dtype.kind not in ['i','f']:
-                raise ArithmeticDateError
-        if self._asdates:
-            return instance.__class__(method(other, *args), 
-                                      freq=freq)
-        else:
-            return method(other, *args)
-
-class DateArray(ndarray):  
-    """Defines a ndarray of dates, as ordinals.
-    
-When viewed globally (array-wise), DateArray is an array of integers.
-When viewed element-wise, DateArray is a sequence of dates.
-For example, a test such as :
->>> DateArray(...) = value
-will be valid only if value is an integer, not a Date
-However, a loop such as :
->>> for d in DateArray(...):
-accesses the array element by element. Therefore, `d` is a Date object.    
-    """
-    _defcachedinfo = dict(toobj=None, tostr=None, toord=None, 
-                          steps=None, full=None, hasdups=None)
-    def __new__(cls, dates=None, freq=None, copy=False):
-        # Get the frequency ......
-        if freq is None:
-            _freq = getattr(dates, 'freq', -9999)
-        else:
-            _freq = corelib.check_freq(freq)
-        cls._defaultfreq = corelib.check_freq(_freq)
-        # Get the dates ..........
-        _dates = numeric.array(dates, copy=copy, dtype=int_, subok=1)
-        if _dates.ndim == 0:
-            _dates.shape = (1,)
-        _dates = _dates.view(cls)
-        _dates.freq = _freq
-        return _dates
-    
-    def __array_wrap__(self, obj, context=None):
-        if context is None:
-            return self
-        elif context[0].__name__ not in ufunc_dateOK:
-            raise ArithmeticDateError, "(function %s)" % context[0].__name__
-    
-    def __array_finalize__(self, obj):
-        self.freq = getattr(obj, 'freq', -9999)
-        self._cachedinfo = dict(toobj=None, tostr=None, toord=None, 
-                                steps=None, full=None, hasdups=None)
-        if hasattr(obj,'_cachedinfo'):
-            self._cachedinfo.update(obj._cachedinfo)
-        return
-    
-    def __getitem__(self, indx):
-        if isinstance(indx, Date):
-            indx = self.find_dates(indx)
-        elif numeric.asarray(indx).dtype.kind == 'O':
-            try:
-                indx = self.find_dates(indx)       
-            except AttributeError:
-                pass     
-        r = ndarray.__getitem__(self, indx)
-        if isinstance(r, (generic, int)):
-            return Date(self.freq, value=r)
-        elif hasattr(r, 'size') and r.size == 1:
-            # need to check if it has a size attribute for situations
-            # like when the datearray is the data for a maskedarray
-            # or some other subclass of ndarray with wierd getitem
-            # behaviour
-            return Date(self.freq, value=r.item())
-        else:
-            if hasattr(r, '_cachedinfo'):
-                r._cachedinfo.update(dict(steps=None, full=None, hasdups=None))
-                for attr in ('tostr','toobj','toord'):
-                    if r._cachedinfo[attr] is not None:
-                        r._cachedinfo[attr] = r._cachedinfo[attr][indx]
-            return r
-        
-    def __repr__(self):
-        return ndarray.__repr__(self)
-    #......................................................
-    __add__ = _datearithmetics('__add__', asdates=True)
-    __radd__ = _datearithmetics('__add__', asdates=True)
-    __sub__ = _datearithmetics('__sub__', asdates=True)
-    __rsub__ = _datearithmetics('__rsub__', asdates=True)
-    __le__ = _datearithmetics('__le__', asdates=False)
-    __lt__ = _datearithmetics('__lt__', asdates=False)
-    __ge__ = _datearithmetics('__ge__', asdates=False)
-    __gt__ = _datearithmetics('__gt__', asdates=False)
-    __eq__ = _datearithmetics('__eq__', asdates=False)
-    __ne__ = _datearithmetics('__ne__', asdates=False)
-    #......................................................
-    @property
-    def freqstr(self):
-        "Returns the frequency string code."
-        return corelib.freq_tostr(self.freq)
-    @property
-    def day(self):          
-        "Returns the day of month."
-        return self.__getdateinfo__('D')
-    @property
-    def day_of_week(self):  
-        "Returns the day of week."
-        return self.__getdateinfo__('W')
-    @property
-    def day_of_year(self):  
-        "Returns the day of year."
-        return self.__getdateinfo__('R')
-    @property
-    def month(self):        
-        "Returns the month."
-        return self.__getdateinfo__('M')
-    @property
-    def quarter(self):   
-        "Returns the quarter."   
-        return self.__getdateinfo__('Q')
-    @property
-    def year(self):         
-        "Returns the year."
-        return self.__getdateinfo__('Y')
-    @property
-    def second(self):    
-        "Returns the seconds."  
-        return self.__getdateinfo__('S')
-    @property
-    def minute(self):     
-        "Returns the minutes."  
-        return self.__getdateinfo__('T')
-    @property
-    def hour(self):         
-        "Returns the hour."
-        return self.__getdateinfo__('H')
-    @property
-    def week(self):
-        "Returns the week."
-        return self.__getdateinfo__('I')
-
-    days = day
-    weekdays = day_of_week
-    yeardays = day_of_year
-    months = month
-    quarters = quarter
-    years = year
-    seconds = second
-    minutes = minute
-    hours = hour
-    weeks = week
-    
-    def __getdateinfo__(self, info):
-        return numeric.asarray(cseries.getDateInfo(numeric.asarray(self), 
-                                                   self.freq, info), 
-                               dtype=int_)
-    __getDateInfo = __getdateinfo__    
-    #.... Conversion methods ....................
-    #
-    def tovalue(self):
-        "Converts the dates to integer values."
-        return numeric.asarray(self)
-    #
-    def toordinal(self):
-        "Converts the dates from values to ordinals."
-        # Note: we better try to cache the result
-        if self._cachedinfo['toord'] is None:
-#            diter = (Date(self.freq, value=d).toordinal() for d in self)
-            diter = (d.toordinal() for d in self)
-            toord = numeric.fromiter(diter, dtype=float_)
-            self._cachedinfo['toord'] = toord
-        return self._cachedinfo['toord']
-    #
-    def tostring(self):
-        "Converts the dates to strings."
-        # Note: we better cache the result
-        if self._cachedinfo['tostr'] is None:
-            firststr = str(self[0])
-            if self.size > 0:
-                ncharsize = len(firststr)
-                tostr = numpy.fromiter((str(d) for d in self),
-                                        dtype='|S%i' % ncharsize)
-            else:
-                tostr = firststr
-            self._cachedinfo['tostr'] = tostr
-        return self._cachedinfo['tostr']
-    #   
-    def asfreq(self, freq=None, relation="BEFORE"):
-        "Converts the dates to another frequency."
-        # Note: As we define a new object, we don't need caching
-        if freq is None or freq == -9999:
-            return self
-        tofreq = corelib.check_freq(freq)
-        if tofreq == self.freq:
-            return self        
-        fromfreq = self.freq
-        _rel = relation.upper()[0]
-        new = cseries.asfreq(numeric.asarray(self), fromfreq, tofreq, _rel)
-        return DateArray(new, freq=freq)
-    #......................................................
-    def find_dates(self, *dates):
-        "Returns the indices corresponding to given dates, as an array."
-        ifreq = self.freq
-        c = numpy.zeros(self.shape, bool_)
-        for d in corelib.flatargs(*dates):
-            if d.freq != ifreq:
-                d = d.asfreq(ifreq)
-            c += (self == d.value)
-        c = c.nonzero()
-        if fromnumeric.size(c) == 0:
-            raise IndexError, "Date out of bounds!"
-        return c  
-
-    def date_to_index(self, date):
-        "Returns the index corresponding to one given date, as an integer."
-        if self.isvalid():
-            index = date.value - self[0].value
-            if index < 0 or index > self.size:
-                raise IndexError, "Date out of bounds!"
-            return index
-        else:
-            index_asarray = (self == date.value).nonzero()
-            if fromnumeric.size(index_asarray) == 0:
-                raise IndexError, "Date out of bounds!" 
-            return index_asarray[0][0]
-    #......................................................        
-    def get_steps(self):
-        """Returns the time steps between consecutive dates.
-    The timesteps have the same unit as the frequency of the series."""
-        if self.freq == 'U':
-            warnings.warn("Undefined frequency: assuming integers!")
-        if self._cachedinfo['steps'] is None:
-            _cached = self._cachedinfo
-            val = numeric.asarray(self).ravel()
-            if val.size > 1:
-                steps = val[1:] - val[:-1]
-                if _cached['full'] is None:
-                    _cached['full'] = (steps.max() == 1)
-                if _cached['hasdups'] is None:
-                    _cached['hasdups'] = (steps.min() == 0)
-            else:
-                _cached['full'] = True
-                _cached['hasdups'] = False
-                steps = numeric.array([], dtype=int_)
-            self._cachedinfo['steps'] = steps
-        return self._cachedinfo['steps']
-    
-    def has_missing_dates(self):
-        "Returns whether the DateArray have missing dates."
-        if self._cachedinfo['full'] is None:
-            steps = self.get_steps()
-        return not(self._cachedinfo['full'])
-    
-    def isfull(self):
-        "Returns whether the DateArray has no missing dates."
-        if self._cachedinfo['full'] is None:
-            steps = self.get_steps()
-        return self._cachedinfo['full']
-    
-    def has_duplicated_dates(self):
-        "Returns whether the DateArray has duplicated dates."
-        if self._cachedinfo['hasdups'] is None:
-            steps = self.get_steps()
-        return self._cachedinfo['hasdups']
-    
-    def isvalid(self):
-        "Returns whether the DateArray is valid: no missing/duplicated dates."
-        return  (self.isfull() and not self.has_duplicated_dates())
-    #......................................................
-
-#............................
-
-
-#####---------------------------------------------------------------------------
-#---- --- DateArray functions ---
-#####---------------------------------------------------------------------------  
-def isDateArray(a):
-    "Tests whether an array is a DateArray object."
-    return isinstance(a,DateArray)
-
-def guess_freq(dates):
-    """Tries to estimate the frequency of a list of dates, by checking the steps
-    between consecutive dates The steps should be in days.
-    Returns a frequency code (alpha character)."""
-    ddif = numeric.asarray(numpy.diff(dates))
-    ddif.sort()
-    if ddif[0] == ddif[-1] == 1.:
-        fcode = 'D'
-    elif (ddif[0] == 1.) and (ddif[-1] == 3.):
-        fcode = 'B'
-    elif (ddif[0] > 3.) and  (ddif[-1] == 7.):
-        fcode = 'W'
-    elif (ddif[0] >= 28.) and (ddif[-1] <= 31.):
-        fcode = 'M'
-    elif (ddif[0] >= 90.) and (ddif[-1] <= 92.):
-        fcode = 'Q'
-    elif (ddif[0] >= 365.) and (ddif[-1] <= 366.):
-        fcode = 'A'
-    elif numpy.abs(24.*ddif[0] - 1) <= 1e-5 and \
-         numpy.abs(24.*ddif[-1] - 1) <= 1e-5:
-        fcode = 'H'
-    elif numpy.abs(1440.*ddif[0] - 1) <= 1e-5 and \
-         numpy.abs(1440.*ddif[-1] - 1) <= 1e-5:
-        fcode = 'T'
-    elif numpy.abs(86400.*ddif[0] - 1) <= 1e-5 and \
-         numpy.abs(86400.*ddif[-1] - 1) <= 1e-5:
-        fcode = 'S'
-    else:
-        warnings.warn("Unable to estimate the frequency! %.3f<>%.3f" %\
-                      (ddif[0], ddif[-1]))
-        fcode = 'U'
-    return fcode
-
-
-def _listparser(dlist, freq=None):
-    "Constructs a DateArray from a list."
-    dlist = numeric.asarray(dlist)
-    dlist.sort()
-    if dlist.ndim == 0:
-        dlist.shape = (1,)
-    # Case #1: dates as strings .................
-    if dlist.dtype.kind == 'S':
-        #...construct a list of ordinals
-        ords = numpy.fromiter((DateTimeFromString(s).toordinal() for s in dlist),
-                               float_)
-        ords += 1
-        #...try to guess the frequency
-        if freq is None:
-            freq = guess_freq(ords)
-        #...construct a list of dates
-        dates = [Date(freq, string=s) for s in dlist]
-    # Case #2: dates as numbers .................
-    elif dlist.dtype.kind in 'if':
-        #...hopefully, they are values
-        if freq is None:
-            freq = guess_freq(dlist)
-        dates = dlist
-    # Case #3: dates as objects .................
-    elif dlist.dtype.kind == 'O':
-        template = dlist[0]
-        #...as Date objects
-        if isinstance(template, Date):
-            dates = numpy.fromiter((d.value for d in dlist), int_)
-        #...as mx.DateTime objects
-        elif hasattr(template,'absdays'):
-            # no freq given: try to guess it from absdays
-            if freq is None:
-                ords = numpy.fromiter((s.absdays for s in dlist), float_)
-                ords += 1
-                freq = guess_freq(ords)
-            dates = [Date(freq, datetime=m) for m in dlist]
-        #...as datetime objects
-        elif hasattr(template, 'toordinal'):
-            ords = numpy.fromiter((d.toordinal() for d in dlist), float_)
-            if freq is None:
-                freq = guess_freq(ords)
-            dates = [Date(freq, datetime=dt.datetime.fromordinal(a)) for a in ords]
-    #
-    result = DateArray(dates, freq)
-    return result
-
-
-def date_array(dlist=None, start_date=None, end_date=None, length=None, 
-               include_last=True, freq=None):
-    """Constructs a DateArray from:
-    - a starting date and either an ending date or a given length.
-    - a list of dates.
-    """
-    freq = corelib.check_freq(freq)
-    # Case #1: we have a list ...................
-    if dlist is not None:
-        # Already a DateArray....................
-        if isinstance(dlist, DateArray):
-            if (freq is not None) and (dlist.freq != corelib.check_freq(freq)):
-                return dlist.asfreq(freq)
-            else:
-                return dlist
-        # Make sure it's a sequence, else that's a start_date
-        if hasattr(dlist,'__len__'):
-            return _listparser(dlist, freq)
-        elif start_date is not None:
-            if end_date is not None:
-                dmsg = "What starting date should be used ? '%s' or '%s' ?"
-                raise DateError, dmsg % (dlist, start_date)
-            else:
-                (start_date, end_date) = (dlist, start_date)
-        else:
-            start_date = dlist
-    # Case #2: we have a starting date ..........
-    if start_date is None:
-        if length == 0:
-            return DateArray([], freq=freq)
-        raise InsufficientDateError
-    if not isDate(start_date):
-        dmsg = "Starting date should be a valid Date instance! "
-        dmsg += "(got '%s' instead)" % type(start_date)
-        raise DateError, dmsg
-    # Check if we have an end_date
-    if end_date is None:
-        if length is None:
-#            raise ValueError,"No length precised!"
-            length = 1
-    else:
-        if not isDate(end_date):
-            raise DateError, "Ending date should be a valid Date instance!"
-        length = int(end_date - start_date)
-        if include_last:
-            length += 1
-#    dlist = [(start_date+i).value for i in range(length)]
-    dlist = numeric.arange(length, dtype=int_)
-    dlist += start_date.value
-    if freq is None:
-        freq = start_date.freq
-    return DateArray(dlist, freq=freq)
-datearray = date_array
-
-def date_array_fromlist(dlist, freq=None):
-    "Constructs a DateArray from a list of dates."
-    return date_array(dlist=dlist, freq=freq)
-
-def date_array_fromrange(start_date, end_date=None, length=None, 
-                         include_last=True, freq=None):
-    """Constructs a DateArray from a starting date and either an ending date or 
-    a length."""
-    return date_array(start_date=start_date, end_date=end_date, 
-                      length=length, include_last=include_last, freq=freq)    
-
-#####---------------------------------------------------------------------------
-#---- --- Definition of functions from the corresponding methods ---
-#####---------------------------------------------------------------------------
-class _frommethod(object):
-    """Defines functions from existing MaskedArray methods.
-:ivar _methodname (String): Name of the method to transform.
-    """
-    def __init__(self, methodname):
-        self._methodname = methodname
-        self.__doc__ = self.getdoc()
-    def getdoc(self):
-        "Returns the doc of the function (from the doc of the method)."
-        try:
-            return getattr(DateArray, self._methodname).__doc__
-        except AttributeError:
-            return "???"
-    #
-    def __call__(self, caller, *args, **params):
-        if hasattr(caller, self._methodname):
-            method = getattr(caller, self._methodname)
-            # If method is not callable, it's a property, and don't call it
-            if hasattr(method, '__call__'):
-                return method.__call__(*args, **params)
-            return method
-        method = getattr(fromnumeric.asarray(caller), self._methodname)
-        try:
-            return method(*args, **params)
-        except SystemError:
-            return getattr(numpy,self._methodname).__call__(caller, *args, **params)
-#............................
-day_of_week = _frommethod('day_of_week')
-day_of_year = _frommethod('day_of_year')
-year = _frommethod('year')
-quarter = _frommethod('quarter')
-month = _frommethod('month')
-day = _frommethod('day')
-hour = _frommethod('hour')
-minute = _frommethod('minute')
-second = _frommethod('second')
-
-
-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]
-
-
-################################################################################
-
-if __name__ == '__main__':
-    import maskedarray.testutils
-    from maskedarray.testutils import assert_equal
-    if 1:
-        dlist = ['2007-%02i' % i for i in range(1,5)+range(7,13)]
-        mdates = date_array_fromlist(dlist, 'M')
-        # Using an integer
-        assert_equal(mdates[0].value, 24073)
-        assert_equal(mdates[-1].value, 24084)
-        # Using a date
-        lag = mdates.find_dates(mdates[0])
-        print mdates[lag]
-        assert_equal(mdates[lag], mdates[0])
-    if 1:
-        hodie = today('D')
-        D = DateArray(today('D'))
-        assert_equal(D.freq, 6000)
-    
-    if 1:
-        freqs = [x[0] for x in corelib.freq_dict.values() if x[0] != 'U']
-        print freqs
-        for f in freqs:
-            print f
-            today = thisday(f)
-            assert(Date(freq=f, value=today.value) == today)
-    
-    if 1:
-        D = date_array(start_date=thisday('D'), length=5)
-        Dstr = D.tostring()
-        assert_equal(D.tostring(), Dstr)
-        DL = D[[0,-1]]
-        assert_equal(DL.tostring(), Dstr[[0,-1]])
-    
\ No newline at end of file




More information about the Scipy-svn mailing list