[Scipy-svn] r2819 - in trunk/Lib/sandbox/timeseries: . addons addons/tests tests

scipy-svn@scip... scipy-svn@scip...
Sat Mar 3 17:00:26 CST 2007


Author: pierregm
Date: 2007-03-03 17:00:20 -0600 (Sat, 03 Mar 2007)
New Revision: 2819

Modified:
   trunk/Lib/sandbox/timeseries/__init__.py
   trunk/Lib/sandbox/timeseries/addons/filters.py
   trunk/Lib/sandbox/timeseries/addons/tests/test_filters.py
   trunk/Lib/sandbox/timeseries/addons/tests/test_interpolate.py
   trunk/Lib/sandbox/timeseries/tdates.py
   trunk/Lib/sandbox/timeseries/tests/test_dates.py
   trunk/Lib/sandbox/timeseries/tests/test_timeseries.py
   trunk/Lib/sandbox/timeseries/tseries.py
Log:
tdates  : separated the case 'D'/'U' in Date
        : improved the handling of 'U' freq
tseries : mask_period : fixed mask_period for multivariables
                        got rid of extra condition on end_date, start_date
                        set the default to inplace=False
        : TimeSeries  : fixed a bug when length was not None
        : fixed end/start_date for multivariables.
filters : revert to initial implementation

Modified: trunk/Lib/sandbox/timeseries/__init__.py
===================================================================
--- trunk/Lib/sandbox/timeseries/__init__.py	2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/__init__.py	2007-03-03 23:00:20 UTC (rev 2819)
@@ -23,6 +23,8 @@
 from tmulti import *
 import reportlib
 from reportlib import *
+import plotlib
+import addons
 
 
 __all__ = ['tdates', 'tseries','tmulti','reportlib']

Modified: trunk/Lib/sandbox/timeseries/addons/filters.py
===================================================================
--- trunk/Lib/sandbox/timeseries/addons/filters.py	2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/addons/filters.py	2007-03-03 23:00:20 UTC (rev 2819)
@@ -29,8 +29,21 @@
 #####---------------------------------------------------------------------------
 #---- --- Moving average functions ---
 #####---------------------------------------------------------------------------
-def __expmave(data, n, tol):
-    """helper function for expmave"""
+def expmave(data, n, tol=1e-6):
+    """Calculates the exponential moving average of a series.
+
+:Parameters:
+    data : ndarray
+        Data as a valid (subclass of) ndarray or MaskedArray. In particular, 
+        TimeSeries objects are valid here.
+    n : int 
+        Time periods. The smoothing factor is 2/(n + 1)
+    tol : float, *[1e-6]*
+        Tolerance for the definition of the mask. When data contains masked 
+        values, this parameter determinea 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.
+"""
     data = marray(data, copy=True, subok=True)
     ismasked = (data._mask is not nomask)
     data._mask = N.zeros(data.shape, bool_)
@@ -48,44 +61,7 @@
     data._mask[0] = True
     #
     return data
-    
-def expmave(data, n, tol=1e-6,
-            centered=False, trailing=False):
-    """Calculates the exponential moving average of a series.
 
-:Parameters:
-    data : ndarray
-        Data as a valid (subclass of) ndarray or MaskedArray. In particular, 
-        TimeSeries objects are valid here.
-    n : int 
-        Time periods. The smoothing factor is 2/(n + 1).
-    tol : float, *[1e-6]*
-        Tolerance for the definition of the mask. When data contains masked 
-        values, this parameter determinea 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.
-    centered : boolean, *[False]*
-        If both centered and trailing are False, then centered is forced to
-        True. If centered, the result at position i is the average of the
-        trailing result with n=n//2, and an equivalent calculation operating in
-        the reverse direction on the series.
-    trailing : boolean, *[False]*
-        If trailing is True, the result at position i uses only data points at,
-        or before, position i.
-"""
-    if not centered and not trailing:
-        centered = True
-    elif centered and trailing:
-        raise ValueError("Cannot specify both centered and trailing")
-
-    if trailing:
-        return __expmave(data, n, tol=tol)
-    else:
-        rev_result = __expmave(data[::-1], n//2, tol=tol)[::-1]
-        fwd_result = __expmave(data, n//2, tol=tol)
-        return (rev_result + fwd_result)/N.array(2, dtype=data.dtype)
-
-
 def weightmave(data, n):
     data = marray(data, subok=True, copy=True)
     data._mask = N.zeros(data.shape, bool_)
@@ -109,31 +85,23 @@
 
 
 #...............................................................................
-def running_window(data, window_type, window_size,
-                   centered=False, trailing=False):
-    """Applies a running window of type window_type and size window_size on the
-data. Returns a (subclass of) MaskedArray.
-
+def running_window(data, window_type, window_size):
+    """Applies a running window of type window_type and size window_size on the 
+    data.
+    
+    Returns a (subclass of) MaskedArray. The k first and k last data are always 
+    masked (with k=window_size//2). When data has a missing value at position i, 
+    the result has missing values in the interval [i-k:i+k+1].
+    
+    
 :Parameters:
     data : ndarray
-        Data to process. The array should be at most 2D. On 2D arrays, the
-        window
+        Data to process. The array should be at most 2D. On 2D arrays, the window
         is applied recursively on each column.
     window_type : string/tuple/float
         Window type (see Notes)
     window_size : integer
         The width of the window.
-    centered : boolean, *[False]*
-        If both centered and trailing are False, then centered is forced to
-        True. If centered, the result at position i uses data points from
-        [i-k:i+k+1] in the calculation. The k first and k last data are always
-        masked (with k=window_size//2). When data has a missing value at
-        position i, the result has missing values in the interval [i-k:i+k+1].
-    trailing : boolean, *[False]*
-        If trailing is True, the result at position i uses data points from
-        [i-window_size:i+1] in the calculation.the first "window_size" data
-        points are always masked. When data has a missing value at position i,
-        the result has missing values in the interval [i-window_size:i+1].
         
 Notes
 -----
@@ -148,24 +116,14 @@
 
 Note also that only boxcar has been thoroughly tested.
     """
-
-    if not centered and not trailing:
-        centered = True
-    elif centered and trailing:
-        raise ValueError("Cannot specify both centered and trailing")
-    
-    
+    #
     data = marray(data, copy=True, subok=True)
     if data._mask is nomask:
         data._mask = N.zeros(data.shape, bool_)
     window = get_window(window_type, window_size, fftbins=False)
-    n = len(data)
-    
-    if centered: k = window_size//2
-    else:        k = 0
-
+    (n, k) = (len(data), window_size//2)
+    #
     if data.ndim == 1:
-        
         data._data.flat = convolve(data._data, window)[k:n+k] / float(window_size)
         data._mask[:] = ((convolve(getmaskarray(data), window) > 0)[k:n+k])
     elif data.ndim == 2:
@@ -175,39 +133,25 @@
             data._mask[:,i] = (convolve(data._mask[:,i], window) > 0)[k:n+k]
     else:
         raise ValueError, "Data should be at most 2D"
-        
-    if centered:
-        data._mask[:k] = data._mask[-k:] = True
-    else:
-        data._mask[:window_size] = True
+    data._mask[:k] = data._mask[-k:] = True
     return data
 
-def running_mean(data, width,
-                 centered=False, trailing=False):
-    """Computes the running mean of size width on the data. Returns a
-(subclass of) MaskedArray.
-
+def running_mean(data, width):
+    """Computes the running mean of size width on the data.
+    
+    Returns a (subclass of) MaskedArray. The k first and k last data are always 
+    masked (with k=window_size//2). When data has a missing value at position i, 
+    the result has missing values in the interval [i-k:i+k+1].
+    
 :Parameters:
     data : ndarray
         Data to process. The array should be at most 2D. On 2D arrays, the window
         is applied recursively on each column.
     window_size : integer
-        The width of the window.
-    centered : boolean, *[False]*
-        If both centered and trailing are False, then centered is forced to
-        True. If centered, the result at position i uses data points from
-        [i-k:i+k+1] in the calculation. The k first and k last data are always
-        masked (with k=window_size//2). When data has a missing value at
-        position i, the result has missing values in the interval [i-k:i+k+1].
-    trailing : boolean, *[False]*
-        If trailing is True, the result at position i uses data points from
-        [i-window_size:i+1] in the calculation.the first "window_size" data
-        points are always masked. When data has a missing value at position i,
-        the result has missing values in the interval [i-window_size:i+1]."""
+        The width of the window.    
+    """
+    return running_window(data, 'boxcar', width)
 
-    return running_window(data, 'boxcar', width,
-                          centered=centered, trailing=trailing)
-
 ################################################################################
 if __name__ == '__main__':
     from maskedarray.testutils import assert_equal, assert_almost_equal

Modified: trunk/Lib/sandbox/timeseries/addons/tests/test_filters.py
===================================================================
--- trunk/Lib/sandbox/timeseries/addons/tests/test_filters.py	2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/addons/tests/test_filters.py	2007-03-03 23:00:20 UTC (rev 2819)
@@ -16,18 +16,15 @@
 from numpy.testing import NumpyTest, NumpyTestCase
 
 import maskedarray.testutils
-#reload(maskedarray.testutils)
 from maskedarray.testutils import *
 
 import maskedarray.core as coremodule
-#reload(coremodule)
 from maskedarray.core import MaskedArray, masked
 
 import tseries
 from tseries import time_series, thisday
 
 import addons.filters
-reload(addons.filters)
 from addons.filters import running_mean
 
 

Modified: trunk/Lib/sandbox/timeseries/addons/tests/test_interpolate.py
===================================================================
--- trunk/Lib/sandbox/timeseries/addons/tests/test_interpolate.py	2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/addons/tests/test_interpolate.py	2007-03-03 23:00:20 UTC (rev 2819)
@@ -14,11 +14,9 @@
 from numpy.testing import NumpyTest, NumpyTestCase
 
 import maskedarray.testutils
-#reload(maskedarray.testutils)
 from maskedarray.testutils import *
 
 import maskedarray.core as coremodule
-#reload(coremodule)
 from maskedarray.core import MaskedArray, masked
 
 from addons.interpolate import backward_fill, forward_fill, interp_masked1d

Modified: trunk/Lib/sandbox/timeseries/tdates.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tdates.py	2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/tdates.py	2007-03-03 23:00:20 UTC (rev 2819)
@@ -3,12 +3,12 @@
 
 :author: Pierre GF Gerard-Marchant & Matt Knox
 :contact: pierregm_at_uga_dot_edu - mattknox_ca_at_hotmail_dot_com
-:version: $Id: tdates.py 2805 2007-03-01 21:40:02Z mattknox_ca $
+:version: $Id$
 """
-__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author: mattknox_ca $)"
+__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author$)"
 __version__ = '1.0'
-__revision__ = "$Revision: 2805 $"
-__date__     = '$Date: 2007-03-01 16:40:02 -0500 (Thu, 01 Mar 2007) $'
+__revision__ = "$Revision$"
+__date__     = '$Date$'
 
 import datetime as dt
 
@@ -35,7 +35,6 @@
 from parser import DateFromString, DateTimeFromString    
 
 import tcore as corelib
-import tcore as _c
 import cseries
 
 
@@ -49,6 +48,7 @@
 'period_break'
            ]
 
+
 #####---------------------------------------------------------------------------
 #---- --- Date Info ---
 #####---------------------------------------------------------------------------
@@ -147,40 +147,40 @@
                 value = int(value)
         
             if isinstance(value, str):
-                if self.freq in (_c.FR_HR, _c.FR_MIN, _c.FR_SEC):
+                if self.freqstr in ('H', 'T', 'S'):
                     self.datetime = DateTimeFromString(value)
                 else:
                     self.datetime = DateFromString(value)
-
-            elif self.freq == _c.FR_SEC:
-                self.datetime = secondlyOriginDate + dt.timedelta(seconds=value)
-            elif self.freq == _c.FR_MIN:
-                self.datetime = minutelyOriginDate + dt.timedelta(minutes=value)
-            elif self.freq == _c.FR_HR:
-                self.datetime = hourlyOriginDate + dt.timedelta(hours=value)
-            elif self.freq in (_c.FR_DAY, _c.FR_UND):
-                self.datetime = dt.datetime.fromordinal(value)
-            elif self.freq == _c.FR_BUS:
+            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.freq == _c.FR_WK:
-                self.datetime = dt.datetime(1,1,7) + \
-                                dt.timedelta(days=(value-1)*7)
-            elif self.freq == _c.FR_MTH:
+#            elif self.freqstr in 'DU':
+            elif self.freqstr == 'D':
+                self.datetime = dt.datetime.fromordinal(value)
+            elif self.freqstr == 'U':
+                self.datetime = int(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.freq == _c.FR_QTR:
+            elif self.freqstr == 'Q':
                 year = (value - 1)//4 + 1
                 month = (value - (year - 1)*4)*3
                 self.datetime = dt.datetime(year, month, 1)
-            elif self.freq == _c.FR_ANN:
-                self.datetime = dt.datetime(value, 1, 1)
-            else:
-                raise ValueError("unrecognized frequency: "+str(self.freq))
+            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.freq in (_c.FR_HR, _c.FR_MIN, _c.FR_SEC):
+            if self.freqstr in ('H', 'T', 'S'):
                 self.datetime = DateTimeFromString(string)
             else:
                 self.datetime = DateFromString(string)
@@ -194,32 +194,31 @@
             # First, some basic checks.....
             if year is None:
                 raise InsufficientDateError            
-            if self.freq in (_c.FR_BUS, _c.FR_DAY, _c.FR_WK, _c.FR_UND):
+            if self.freqstr in 'BDWU':
                 if month is None or day is None: 
                     raise InsufficientDateError
-            elif self.freq == _c.FR_MTH:
+            elif self.freqstr == 'M':
                 if month is None: 
                     raise InsufficientDateError
                 day = 1
-            elif self.freq == _c.FR_QTR:
+            elif self.freqstr == 'Q':
                 if quarter is None: 
                     raise InsufficientDateError
                 month = quarter * 3
                 day = 1
-            elif self.freq == _c.FR_ANN:
+            elif self.freqstr == 'A':
                 month = 1
                 day = 1
-            elif self.freq == _c.FR_SEC:
+            elif self.freqstr == 'S':
                 if month is None or day is None or second is None: 
                     raise InsufficientDateError
                 
-            if self.freq in (_c.FR_BUS, _c.FR_DAY, _c.FR_WK,
-                             _c.FR_MTH, _c.FR_QTR, _c.FR_ANN):
+            if self.freqstr in ['A','B','D','M','Q','W']:
                 self.datetime = truncateDate(self.freq, dt.datetime(year, month, day))
-                if self.freq == _c.FR_BUS:
+                if self.freqstr == 'B':
                     if self.datetime.isoweekday() in [6,7]:
                         raise ValueError("Weekend passed as business day")
-            elif self.freq in (_c.FR_HR, _c.FR_MIN, _c.FR_SEC):
+            elif self.freqstr in 'HTS':
                 if hour is None:
                     if minute is None:
                         if second is None:
@@ -240,9 +239,6 @@
                 self.datetime = truncateDate(self.freqstr,
                                              dt.datetime(year, month, day, 
                                                          hour, minute, second))
-            else:
-                raise ValueError("unrecognized frequency: "+str(self.freq))
-
         self.value = self.__value()
 
     def __getitem__(self, indx):
@@ -340,45 +336,53 @@
     
     def __value(self):   
         "Converts the date to an integer, depending on the current frequency."
-        # Secondly......
-        if self.freq == _c.FR_SEC:
-            delta = (self.datetime - secondlyOriginDate)
-            val = delta.days*86400 + delta.seconds
-        # Minutely......
-        elif self.freq == _c.FR_MIN:
-            delta = (self.datetime - minutelyOriginDate)
-            val = delta.days*1440 + delta.seconds/(60)
-        # Hourly........
-        elif self.freq == _c.FR_HR:
-            delta = (self.datetime - hourlyOriginDate)
-            val = delta.days*24 + delta.seconds/(3600)
-        # Daily/undefined
-        elif self.freq in (_c.FR_DAY, _c.FR_UND):
-            val = self.datetime.toordinal()
+        # 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.freq == _c.FR_BUS:
+        elif self.freqstr == 'B':
             days = self.datetime.toordinal()
             weeks = days // 7
             val = days - weeks*2  
-        # Weekly........
-        elif self.freq == _c.FR_WK:
-            val = self.datetime.toordinal()//7
-        # Monthly.......
-        elif self.freq == _c.FR_MTH:
-            val = (self.datetime.year-1)*12 + self.datetime.month
-        # Quarterly.....
-        elif self.freq == _c.FR_QTR:
-            val = (self.datetime.year-1)*4 + self.datetime.month//3
-        # Annual .......
-        elif self.freq == _c.FR_ANN:
-            val = self.datetime.year
-
+        # Daily.........
+#        elif self.freqstr in 'DU':
+        elif self.freqstr == 'D':
+            val = self.datetime.toordinal()
+        # Undefined.....
+        elif self.freqstr == 'U':
+            if not hasattr(self.datetime, 'toordinal'):
+                val = self.datetime
+            else:
+                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]
+        if self.freqstr == 'U':
+            return str(self.value)
         return cseries.strfmt(self.datetime, fmt)
             
     def __str__(self):
@@ -389,6 +393,9 @@
     #......................................................
     def toordinal(self):
         "Returns the date as an ordinal."
+        # FIXME: We shouldn't need the test if we were in C
+        if self.freqstr == 'U':
+            return self.value
         return self.datetime.toordinal()
 
     def fromordinal(self, ordinal):
@@ -425,26 +432,26 @@
 
 def truncateDate(freq, datetime):
     "Chops off the irrelevant information from the datetime object passed in."
-    freq = corelib.check_freq(freq)
-    if freq == _c.FR_MIN:
+    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)
-    elif freq == _c.FR_HR:
-        return dt.datetime(datetime.year, datetime.month, datetime.day, \
-                           datetime.hour)
-    elif freq in (_c.FR_BUS, _c.FR_DAY):
-        if freq == _c.FR_BUS and datetime.isoweekday() in (6,7):
-            raise ValueError("Weekend passed as business day")
-        return dt.datetime(datetime.year, datetime.month, datetime.day)
-    elif freq == _c.FR_WK:
-        d = datetime.toordinal()
-        return dt.datetime.fromordinal(d + (7 - d % 7) % 7)
-    elif freq == _c.FR_MTH:
-        return dt.datetime(datetime.year, datetime.month, 1)
-    elif freq == _c.FR_QTR:
-        return dt.datetime(datetime.year, monthToQuarter(datetime.month)*3, 1)
-    elif freq == _c.FR_ANN:
-        return dt.datetime(datetime.year, 1, 1)
     else:
         return datetime
     
@@ -455,20 +462,18 @@
 
 def thisday(freq):
     "Returns today's date, at the given frequency `freq`."
-    freq = corelib.check_freq(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 freq == _c.FR_BUS and tempDate.isoweekday() >= 6:
+    if freqstr == 'B' and tempDate.isoweekday() >= 6:
         tempDate = tempDate - dt.timedelta(days=(tempDate.isoweekday() - 5))
-    if freq in (_c.FR_BUS,_c.FR_DAY,
-                _c.FR_HR,_c.FR_SEC,_c.FR_MIN,
-                _c.FR_WK,_c.FR_UND):
+    if freqstr in ('B','D','H','S','T','W','U'):
         return Date(freq, datetime=tempDate)
-    elif freq == _c.FR_MTH:
+    elif freqstr == 'M':
         return Date(freq, year=tempDate.year, month=tempDate.month)
-    elif freq == _c.FR_QTR:
+    elif freqstr == 'Q':
         return Date(freq, year=tempDate.year, quarter=monthToQuarter(tempDate.month))
-    elif freq == _c.FR_ANN:
+    elif freqstr == 'A':
         return Date(freq, year=tempDate.year)
 today = thisday
 
@@ -478,9 +483,9 @@
     dateNum = tempDate.hour + float(tempDate.minute)/60
     checkNum = day_end_hour + float(day_end_min)/60
     if dateNum < checkNum: 
-        return thisday(_c.FR_BUS) - 1
+        return thisday('B') - 1
     else: 
-        return thisday(_c.FR_BUS)
+        return thisday('B')
                 
 def asfreq(date, toFreq, relation="BEFORE"):
     """Returns a date converted to another frequency `toFreq`, according to the
@@ -494,9 +499,9 @@
     if not isinstance(date, Date):
         raise DateError, "Date should be a valid Date instance!"
 
-    if date.freq == _c.FR_UND:
+    if date.freqstr == 'U':
         warnings.warn("Undefined frequency: assuming daily!")
-        fromfreq = _c.FR_DAY
+        fromfreq = corelib.freq_revdict['D']
     else:
         fromfreq = date.freq
     
@@ -638,7 +643,8 @@
             return r
         
     def __repr__(self):
-        return ndarray.__repr__(self)
+        return ndarray.__repr__(self)[:-1] + \
+               ",\n          freq='%s')" % self.freqstr
     #......................................................
     __add__ = _datearithmetics('__add__', asdates=True)
     __radd__ = _datearithmetics('__add__', asdates=True)
@@ -723,7 +729,10 @@
         # 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)
+            if self.freq == -9999:
+                diter = (d.value for d in self)
+            else:
+                diter = (d.toordinal() for d in self)
             toord = numeric.fromiter(diter, dtype=float_)
             self._cachedinfo['toord'] = toord
         return self._cachedinfo['toord']
@@ -749,9 +758,11 @@
             return self
         tofreq = corelib.check_freq(freq)
         if tofreq == self.freq:
-            return self        
+            return self    
+        _rel = relation.upper()[0]    
         fromfreq = self.freq
-        _rel = relation.upper()[0]
+        if fromfreq == -9999:
+             fromfreq = 6000
         new = cseries.asfreq(numeric.asarray(self), fromfreq, tofreq, _rel)
         return DateArray(new, freq=freq)
     #......................................................
@@ -842,30 +853,30 @@
     ddif = numeric.asarray(numpy.diff(dates))
     ddif.sort()
     if ddif[0] == ddif[-1] == 1.:
-        fcode = _c.FR_DAY
+        fcode = 'D'
     elif (ddif[0] == 1.) and (ddif[-1] == 3.):
-        fcode = _c.FR_BUS
+        fcode = 'B'
     elif (ddif[0] > 3.) and  (ddif[-1] == 7.):
-        fcode = _c.FR_WK
+        fcode = 'W'
     elif (ddif[0] >= 28.) and (ddif[-1] <= 31.):
-        fcode = _c.FR_MTH
+        fcode = 'M'
     elif (ddif[0] >= 90.) and (ddif[-1] <= 92.):
-        fcode = _c.FR_QTR
+        fcode = 'Q'
     elif (ddif[0] >= 365.) and (ddif[-1] <= 366.):
-        fcode = _c.FR_ANN
+        fcode = 'A'
     elif numpy.abs(24.*ddif[0] - 1) <= 1e-5 and \
          numpy.abs(24.*ddif[-1] - 1) <= 1e-5:
-        fcode = _c.FR_HR
+        fcode = 'H'
     elif numpy.abs(1440.*ddif[0] - 1) <= 1e-5 and \
          numpy.abs(1440.*ddif[-1] - 1) <= 1e-5:
-        fcode = _c.FR_MIN
+        fcode = 'T'
     elif numpy.abs(86400.*ddif[0] - 1) <= 1e-5 and \
          numpy.abs(86400.*ddif[-1] - 1) <= 1e-5:
-        fcode = _c.FR_SEC
+        fcode = 'S'
     else:
         warnings.warn("Unable to estimate the frequency! %.3f<>%.3f" %\
                       (ddif[0], ddif[-1]))
-        fcode = _c.FR_UND
+        fcode = 'U'
     return fcode
 
 
@@ -1042,7 +1053,7 @@
 if __name__ == '__main__':
     import maskedarray.testutils
     from maskedarray.testutils import assert_equal
-    if 1:
+    if 0:
         dlist = ['2007-%02i' % i for i in range(1,5)+range(7,13)]
         mdates = date_array_fromlist(dlist, 'M')
         # Using an integer
@@ -1052,12 +1063,12 @@
         lag = mdates.find_dates(mdates[0])
         print mdates[lag]
         assert_equal(mdates[lag], mdates[0])
-    if 1:
+    if 0:
         hodie = today('D')
         D = DateArray(today('D'))
         assert_equal(D.freq, 6000)
     
-    if 1:
+    if 0:
         freqs = [x[0] for x in corelib.freq_dict.values() if x[0] != 'U']
         print freqs
         for f in freqs:
@@ -1066,9 +1077,16 @@
             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
+        D = date_array(freq='U', start_date=Date('U',1), length=10)
+    
+    if 1:
+        dlist = ['2007-01-%02i' % i for i in (1,2,4,5,7,8,10,11,13)]
+        
+        
+        ords = numpy.fromiter((DateTimeFromString(s).toordinal() for s in dlist),
+                               float_)
+        
+    if 1:
+        "Tests the automatic sorting of dates."
+        D = date_array_fromlist(dlist=['2006-01','2005-01','2004-01'],freq='M')
+        assert_equal(D.view(N.ndarray), [24037, 24049, 24061])
\ No newline at end of file

Modified: trunk/Lib/sandbox/timeseries/tests/test_dates.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tests/test_dates.py	2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/tests/test_dates.py	2007-03-03 23:00:20 UTC (rev 2819)
@@ -715,9 +715,11 @@
         assert_equal(mdates>=mdates[-4], [0,0,0,0,0,0,1,1,1,1])
         dlist = ['2006-%02i' % i for i in range(1,5)+range(7,13)]
         mdates = date_array_fromlist(dlist).asfreq('M')
+        #CHECK : Oops, what were we supposed to do here ?
 
         
     def test_getsteps(self):
+        "Tests the getsteps method"
         dlist = ['2007-01-%02i' %i for i in (1,2,3,4,8,9,10,11,12,15)]
         ddates = date_array_fromlist(dlist)
         assert_equal(ddates.get_steps(), [1,1,1,4,1,1,1,1,3])
@@ -729,8 +731,13 @@
         assert_equal(empty_darray.isvalid(), True)
         assert_equal(empty_darray.get_steps(), None)
         
+    def test_cachedinfo(self):
+        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]])
 
-
 ###############################################################################
 #------------------------------------------------------------------------------
 if __name__ == "__main__":

Modified: trunk/Lib/sandbox/timeseries/tests/test_timeseries.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tests/test_timeseries.py	2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/tests/test_timeseries.py	2007-03-03 23:00:20 UTC (rev 2819)
@@ -25,8 +25,9 @@
 import maskedarray.testutils
 from maskedarray.testutils import assert_equal, assert_array_equal
 
-from timeseries import Date, date_array_fromlist, date_array, thisday
-from timeseries import time_series, TimeSeries, adjust_endpoints, \
+from timeseries import tseries
+from timeseries.tseries import Date, date_array_fromlist, date_array, thisday
+from timeseries.tseries import time_series, TimeSeries, adjust_endpoints, \
     mask_period, align_series, fill_missing_dates, tsmasked, concatenate_series
 
 class test_creation(NumpyTestCase):
@@ -422,6 +423,15 @@
         mask = mask_period(series, start, end, inside=False, include_edges=False,
                            inplace=False)
         assert_equal(mask._mask, [1,1,1,1,1,0,0,0,0,0,0,0,1,1,1])
+        # Now w/ multivariables
+        data = masked_array(numeric.arange(30).reshape(-1,2), dtype=float_)
+        series = time_series(data, dates=dates)
+        mask = mask_period(series, start, end, inside=True, include_edges=True,
+                           inplace=False)
+        result = N.array([0,0,0,0,0,1,1,1,1,1,1,1,0,0,0])
+        assert_equal(mask._mask, result.repeat(2).reshape(-1,2))
+        
+        
     #
     def test_pickling(self):
         "Tests pickling/unpickling"

Modified: trunk/Lib/sandbox/timeseries/tseries.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tseries.py	2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/tseries.py	2007-03-03 23:00:20 UTC (rev 2819)
@@ -308,7 +308,7 @@
             if len(dshape) > 0:
                 if length is None:
                     length = dshape[0]
-                newdates = date_array(start_date=start_date, length=dshape[0],
+                newdates = date_array(start_date=start_date, length=length,
                                       freq=freq)
             else:
                 newdates = date_array([], freq=freq)          
@@ -610,17 +610,25 @@
     @property
     def start_date(self):
         """Returns the first date of the series."""
-        if self._dates.size != 0:
-            return self._dates[0]
+        _dates = self._dates
+        dsize = _dates.size
+        if dsize == 0:
+            return None
+        elif dsize == 1:
+            return _dates[0]
         else:
-            return None
+            return Date(self.freq, _dates.flat[0])
     @property
     def end_date(self):
         """Returns the last date of the series."""
-        if self._dates.size != 0:
-            return self._dates[-1]
+        _dates = self._dates
+        dsize = _dates.size
+        if dsize == 0:
+            return None
+        elif dsize == 1:
+            return _dates[-1]
         else:
-            return None
+            return Date(self.freq, _dates.flat[-1])
     
     def isvalid(self):
         """Returns whether the series has no duplicate/missing dates."""
@@ -920,14 +928,16 @@
 ##### --------------------------------------------------------------------------
 #---- ... Additional functions ...
 ##### --------------------------------------------------------------------------
-def mask_period(data, start_date=None, end_date=None, 
-                inside=True, include_edges=True, inplace=True):
+def mask_period(data, period=None, start_date=None, end_date=None, 
+                inside=True, include_edges=True, inplace=False):
     """Returns x as an array masked where dates fall outside the selection period,
 as well as where data are initially missing (masked).
 
 :Parameters:
     data : Timeseries
         Data to process
+    period : Sequence
+        A sequence of (starting date, ending date).
     start_date : string/Date *[None]*
         Starting date. If None, uses the first date of the series.
     end_date : string/Date *[None]*
@@ -943,47 +953,50 @@
     data = masked_array(data, subok=True, copy=not inplace)
     if not isTimeSeries(data):
         raise ValueError,"Data should be a valid TimeSeries!"
+    dates = data._dates
+    if dates.ndim == 1:
+        dates_lims = dates[[0,-1]]
+    else:
+        dates_lim = dates.ravel()[[0,-1]]
+    # Check the period .....................
+    if period is not None and isinstance(period, (tuple, list, ndarray)):
+        (start_date, end_date) = (period[0], period[-1])    
     # Check the starting date ..............
     if start_date is None:
-        start_date = data._dates[0]
+        start_date = dates_lim[0]
     elif isinstance(start_date, str):
         start_date = Date(data.freq, string=start_date)
     elif not isinstance(start_date, Date):
         raise DateError,"Starting date should be a valid Date object!"
-    start_date = max(start_date, data.dates[0])
     # Check the ending date ................
     if end_date is None:
-        end_date = data._dates[-1]
+        end_date = dates_lim[-1]
     elif isinstance(end_date, str):
         end_date = Date(data.freq, string=end_date)
     elif not isinstance(end_date, Date):
         raise DateError,"Starting date should be a valid Date object!"
-    end_date = min(end_date, data.dates[-1])
     # Constructs the selection mask .........
+    dates = data.dates
     if inside:
         if include_edges:
-            selection = (data.dates >= start_date) & (data.dates <= end_date)
+            selection = (dates >= start_date) & (dates <= end_date)
         else:
-            selection = (data.dates > start_date) & (data.dates < end_date)
+            selection = (dates > start_date) & (dates < end_date)
     else:
         if include_edges:
-            selection = (data.dates <= start_date) | (data.dates >= end_date)
+            selection = (dates <= start_date) | (dates >= end_date)
         else:
-            selection = (data.dates < start_date) | (data.dates > end_date)
-    # Process the data:
-    if data._mask is nomask:
-        data._mask = selection
-    else:
-        data._mask += selection
+            selection = (dates < start_date) | (dates > end_date)
+    data[selection] = masked
     return data
 
 def mask_inside_period(data, start_date=None, end_date=None, 
-                       include_edges=True, inplace=True):
+                       include_edges=True, inplace=False):
     """Masks values falling inside a given range of dates."""
     return mask_period(data, start_date=start_date, end_date=end_date, 
                        inside=True, include_edges=include_edges, inplace=inplace)
 def mask_outside_period(data, start_date=None, end_date=None, 
-                       include_edges=True, inplace=True):
+                       include_edges=True, inplace=False):
     """Masks values falling outside a given range of dates."""
     return mask_period(data, start_date=start_date, end_date=end_date, 
                        inside=False, include_edges=include_edges, inplace=inplace)
@@ -1374,6 +1387,8 @@
         dlist = ['2007-01-%02i' % i for i in range(1,11)]
         dates = date_array_fromlist(dlist)
         data = masked_array(numeric.arange(10), mask=[1,0,0,0,0]*2, dtype=float_)
+    
+    if 0:
         ser1d = time_series(data, dlist)
         
         serfolded = ser1d.reshape((5,2))
@@ -1385,21 +1400,17 @@
         sertrans = serfolded.transpose()
         assert_equal(sertrans.shape, (2,5))
         
-    if 1:
-        dlist = ['2007-01-%02i' % i for i in range(1,16)]
-        data = masked_array(numeric.arange(15), mask=[1,0,0,0,0]*3, dtype=float_)
-        series = time_series(data, dlist)
-        series.mask = nomask
-        (start, end) = ('2007-01-06', '2007-01-12')
-        mask = mask_period(series, start, end, inside=True, include_edges=True,
-                           inplace=False)
-        assert_equal(mask._mask, N.array([0,0,0,0,0,1,1,1,1,1,1,1,0,0,0]))
-        mask = mask_period(series, start, end, inside=True, include_edges=False,
-                           inplace=False)
-        assert_equal(mask._mask, [0,0,0,0,0,0,1,1,1,1,1,0,0,0,0])
-        mask = mask_period(series, start, end, inside=False, include_edges=True,
-                           inplace=False)
-        assert_equal(mask._mask, [1,1,1,1,1,1,0,0,0,0,0,1,1,1,1])
-        mask = mask_period(series, start, end, inside=False, include_edges=False,
-                           inplace=False)
-        assert_equal(mask._mask, [1,1,1,1,1,0,0,0,0,0,0,0,1,1,1])
\ No newline at end of file
+    if 1:        
+        data = dates
+        series = time_series(data, dates)
+        assert(isinstance(series, TimeSeries))
+        assert_equal(series._dates, dates)
+        assert_equal(series._data, data)
+        assert_equal(series.freqstr, 'D')
+        
+        series[5] = MA.masked
+        
+        # ensure that series can be represented by a string after masking a value
+        # (there was a bug before that prevented this from working when using a 
+        # DateArray for the data)
+        strrep = str(series)
\ No newline at end of file



More information about the Scipy-svn mailing list