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

scipy-svn at scipy.org scipy-svn at scipy.org
Mon Feb 19 02:37:45 EST 2007


Author: pierregm
Date: 2007-02-19 01:37:26 -0600 (Mon, 19 Feb 2007)
New Revision: 2726

Modified:
   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  : ensures compatibility w/ new MaskedArray + misc cleanup
tseries : ensures compatibility w/ new MaskedArray + misc cleanup

Modified: trunk/Lib/sandbox/timeseries/tdates.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tdates.py	2007-02-19 06:52:16 UTC (rev 2725)
+++ trunk/Lib/sandbox/timeseries/tdates.py	2007-02-19 07:37:26 UTC (rev 2726)
@@ -21,6 +21,8 @@
 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
 #reload(MA)
@@ -225,47 +227,48 @@
     @property
     def day(self):          
         "Returns the day of month."
-        return self.__getDateInfo('D')
+        return self.__getdateinfo__('D')
     @property
     def day_of_week(self):  
         "Returns the day of week."
-        return self.__getDateInfo('W')
+        return self.__getdateinfo__('W')
     @property
     def day_of_year(self):  
         "Returns the day of year."
-        return self.__getDateInfo('R')
+        return self.__getdateinfo__('R')
     @property
     def month(self):        
         "Returns the month."
-        return self.__getDateInfo('M')
+        return self.__getdateinfo__('M')
     @property
     def quarter(self):   
         "Returns the quarter."   
-        return self.__getDateInfo('Q')
+        return self.__getdateinfo__('Q')
     @property
     def year(self):         
         "Returns the year."
-        return self.__getDateInfo('Y')
+        return self.__getdateinfo__('Y')
     @property
     def second(self):    
         "Returns the seconds."  
-        return self.__getDateInfo('S')
+        return self.__getdateinfo__('S')
     @property
     def minute(self):     
         "Returns the minutes."  
-        return self.__getDateInfo('T')
+        return self.__getdateinfo__('T')
     @property
     def hour(self):         
         "Returns the hour."
-        return self.__getDateInfo('H')
+        return self.__getdateinfo__('H')
     @property
     def week(self):
         "Returns the week."
-        return self.__getDateInfo('I')
+        return self.__getdateinfo__('I')
         
-    def __getDateInfo(self, info):
+    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):
@@ -497,24 +500,19 @@
 >>> for d in DateArray(...):
 accesses the array element by element. Therefore, `d` is a Date object.    
     """
-    def __new__(cls, dates=None, freq='U', copy=False):
-        if isinstance(dates, DateArray):
-            cls.__defaultfreq = dates.freq
-            if not copy:
-                return dates.view(cls)
-            return dates.copy().view(cls)
+    (_tostr, _toord, _steps) = (None, None, None)
+    def __new__(cls, dates=None, freq=None, copy=False):
+        # Get the frequency ......
+        if freq is None:
+            _freq = getattr(dates, 'freq', -9999)
         else:
-            _dates = numeric.asarray(dates, dtype=int_)
-            if _dates.ndim == 0:
-                _dates.shape = (1,)
-            if copy:
-                _dates = _dates.copy()
-            if freq is None:
-                freq = 'U'
-            cls.__defaultfreq = corelib.check_freq(freq)
-            (cls.__toobj, cls.__toord, cls.__tostr) = (None, None, None)
-            (cls.__steps, cls.__full, cls.__hasdups) = (None, None, None)
-            return _dates.view(cls)
+            _freq = freq
+        cls._defaultfreq = corelib.check_freq(freq)
+        # Get the dates ..........
+        _dates = numeric.array(dates, copy=copy, dtype=int_, subok=1).view(cls)
+        if _dates.ndim == 0:
+            _dates.shape = (1,)
+        return _dates
     
     def __array_wrap__(self, obj, context=None):
         if context is None:
@@ -523,33 +521,26 @@
             raise ArithmeticDateError, "(function %s)" % context[0].__name__
     
     def __array_finalize__(self, obj):
-        if hasattr(obj, 'freq'):
-            self.freq = obj.freq
-            self.freqstr = obj.freqstr
-        else:
-            self.freq = self.__defaultfreq
-            self.freqstr = corelib.freq_tostr(self.__defaultfreq)
+        self.freq = getattr(obj, 'freq', self._defaultfreq)
+        self.freqstr = getattr(obj, 'freqstr', corelib.freq_tostr(self.freq))
+        for attr in ('_toobj','_toord','_tostr',
+                     '_steps','_full','_hasdups'):
+            setattr(self, attr, getattr(obj, attr, None))
+        return
     
     def __getitem__(self, indx):
         if isinstance(indx, Date):
-            index = self.find_dates(indx)
+            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)
-#        return r
-        if not hasattr(r, "size"):
-            if isinstance(r, int): 
-                return Date(self.freq, value=r)
-            else: 
-                return r
-        elif r.size == 1:
-            # Only one element, and it's not a scalar: we have a DateArray of size 1
-            if len(r.shape) > 0:
-                r = r.item()
+        if isinstance(r, (generic, int)):
             return Date(self.freq, value=r)
+        elif r.size == 1:
+            return Date(self.freq, value=r.item())
         else:
             return r
         
@@ -559,43 +550,43 @@
     @property
     def day(self):          
         "Returns the day of month."
-        return self.__getDateInfo('D')
+        return self.__getDateInfo__('D')
     @property
     def day_of_week(self):  
         "Returns the day of week."
-        return self.__getDateInfo('W')
+        return self.__getDateInfo__('W')
     @property
     def day_of_year(self):  
         "Returns the day of year."
-        return self.__getDateInfo('R')
+        return self.__getDateInfo__('R')
     @property
     def month(self):        
         "Returns the month."
-        return self.__getDateInfo('M')
+        return self.__getDateInfo__('M')
     @property
     def quarter(self):   
         "Returns the quarter."   
-        return self.__getDateInfo('Q')
+        return self.__getDateInfo__('Q')
     @property
     def year(self):         
         "Returns the year."
-        return self.__getDateInfo('Y')
+        return self.__getDateInfo__('Y')
     @property
     def second(self):    
         "Returns the seconds."  
-        return self.__getDateInfo('S')
+        return self.__getDateInfo__('S')
     @property
     def minute(self):     
         "Returns the minutes."  
-        return self.__getDateInfo('T')
+        return self.__getDateInfo__('T')
     @property
     def hour(self):         
         "Returns the hour."
-        return self.__getDateInfo('H')
+        return self.__getDateInfo__('H')
     @property
     def week(self):
         "Returns the week."
-        return self.__getDateInfo('I')
+        return self.__getDateInfo__('I')
 
     days = day
     weekdays = day_of_week
@@ -620,17 +611,17 @@
     def toordinal(self):
         "Converts the dates from values to ordinals."
         # Note: we better try to cache the result
-        if self.__toord is None:
+        if self._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.__toord = toord
-        return self.__toord
+            self._toord = toord
+        return self._toord
     #
     def tostring(self):
         "Converts the dates to strings."
         # Note: we better cache the result
-        if self.__tostr is None:
+        if self._tostr is None:
             firststr = str(self[0])
             if self.size > 0:
                 ncharsize = len(firststr)
@@ -638,22 +629,18 @@
                                         dtype='|S%i' % ncharsize)
             else:
                 tostr = firststr
-            self.__tostr = tostr
-        return self.__tostr
+            self._tostr = tostr
+        return self._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:
+        if freq is None or freq == -9999:
             return self
         tofreq = corelib.check_freq(freq)
         if tofreq == self.freq:
             return self        
-        if self.freqstr == 'U':
-            warnings.warn("Undefined frequency: assuming daily!")
-            fromfreq = corelib.freq_revdict['D']
-        else:
-            fromfreq = self.freq
+        fromfreq = self.freq
         _rel = relation.upper()[0]
         new = cseries.asfreq(numeric.asarray(self), fromfreq, tofreq, _rel)
         return DateArray(new, freq=freq)
@@ -673,62 +660,54 @@
 
     def date_to_index(self, date):
         "Returns the index corresponding to one given date, as an integer."
-        if isDate(date):
-            if self.isvalid():
-                index = date.value - self[0].value
-                if index < 0 or index > self.size:
-                    raise ValueError, "Date out of bounds!"
-                return index
-            else:
-                index_asarray = (self == date.value).nonzero()
-                if fromnumeric.size(index_asarray) == 0:
-                    raise ValueError, "Date out of bounds!" 
-                return index_asarray[0][0]
+        if self.isvalid():
+            index = date.value - self[0].value
+            if index < 0 or index > self.size:
+                raise ValueError, "Date out of bounds!"
+            return index
         else:
-            #date is a DateArray
-            def idx_check(val): return (date == val).any()
-            idx_check_v = numpy.vectorize(idx_check)
-            return numpy.where(idx_check_v(self.tovalue()))[0]
-            
-            
+            index_asarray = (self == date.value).nonzero()
+            if fromnumeric.size(index_asarray) == 0:
+                raise ValueError, "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 daily!")
-        if self.__steps is None:
+            warnings.warn("Undefined frequency: assuming integers!")
+        if self._steps is None:
             val = numeric.asarray(self).ravel()
             if val.size > 1:
                 steps = val[1:] - val[:-1]
-                if self.__full is None:
-                    self.__full = (steps.max() == 1)
-                if self.__hasdups is None:
-                    self.__hasdups = (steps.min() == 0)
+                if self._full is None:
+                    self._full = (steps.max() == 1)
+                if self._hasdups is None:
+                    self._hasdups = (steps.min() == 0)
             else:
-                self.__full = True
-                self.__hasdups = False
+                self._full = True
+                self._hasdups = False
                 steps = numeric.array([], dtype=int_)
-            self.__steps = steps
-        return self.__steps
+            self._steps = steps
+        return self._steps
     
     def has_missing_dates(self):
         "Returns whether the DateArray have missing dates."
-        if self.__full is None:
+        if self._full is None:
             steps = self.get_steps()
-        return not(self.__full)
+        return not(self._full)
     
     def isfull(self):
         "Returns whether the DateArray has no missing dates."
-        if self.__full is None:
+        if self._full is None:
             steps = self.get_steps()
-        return self.__full
+        return self._full
     
     def has_duplicated_dates(self):
         "Returns whether the DateArray has duplicated dates."
-        if self.__hasdups is None:
+        if self._hasdups is None:
             steps = self.get_steps()
-        return self.__hasdups
+        return self._hasdups
     
     def isvalid(self):
         "Returns whether the DateArray is valid: no missing/duplicated dates."
@@ -958,7 +937,7 @@
         "Returns the doc of the function (from the doc of the method)."
         try:
             return getattr(DateArray, self._methodname).__doc__
-        except:
+        except AttributeError:
             return "???"
     #
     def __call__(self, caller, *args, **params):
@@ -988,9 +967,14 @@
 ################################################################################
 
 if __name__ == '__main__':
-    assert (Date('D','2007-01')==Date('D',string='2007-01'))
-    assert (Date('D','2007-01')==Date('D', value=732677))
-    assert (Date('D',732677)==Date('D', value=732677))
-    n = Date('D','2007-01')
-    tmp = date_array(n,n+3)
-    print tmp[0]
\ No newline at end of file
+    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])
\ No newline at end of file

Modified: trunk/Lib/sandbox/timeseries/tests/test_dates.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tests/test_dates.py	2007-02-19 06:52:16 UTC (rev 2725)
+++ trunk/Lib/sandbox/timeseries/tests/test_dates.py	2007-02-19 07:37:26 UTC (rev 2726)
@@ -25,13 +25,18 @@
 import maskedarray.testutils
 from maskedarray.testutils import assert_equal, assert_array_equal
 
-from timeseries import tdates
-#reload(tdates)
+import timeseries.tdates as tdates
+reload(tdates)
+#from timeseries import tdates
+##reload(tdates)
+#from timeseries.tdates import date_array_fromlist, Date, DateArray, date_array,\
+#    mxDFromString, today
+from timeseries.tdates import *
+from timeseries.tdates import mxDFromString
 from timeseries import tcore
 #reload(tcore)
-from timeseries.tdates import date_array_fromlist, Date, DateArray, date_array,\
-    mxDFromString, today
 
+
 class test_creation(NumpyTestCase):
     "Base test class for MaskedArrays."
     

Modified: trunk/Lib/sandbox/timeseries/tests/test_timeseries.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tests/test_timeseries.py	2007-02-19 06:52:16 UTC (rev 2725)
+++ trunk/Lib/sandbox/timeseries/tests/test_timeseries.py	2007-02-19 07:37:26 UTC (rev 2726)
@@ -178,7 +178,8 @@
         series.mask = nomask
         assert(series._mask is nomask)
         assert(series._series._mask is nomask)
-        series._series.mask = [1,0,0]*5
+        #series._series.mask = [1,0,0]*5
+        series.mask = [1,0,0]*5
         assert_equal(series._mask, [1,0,0]*5)
         assert_equal(series._series._mask, [1,0,0]*5)
         series[2] = masked

Modified: trunk/Lib/sandbox/timeseries/tseries.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tseries.py	2007-02-19 06:52:16 UTC (rev 2725)
+++ trunk/Lib/sandbox/timeseries/tseries.py	2007-02-19 07:37:26 UTC (rev 2726)
@@ -35,7 +35,7 @@
 #from numpy.core.records import recarray
 from numpy.core.records import fromarrays as recfromarrays
 
-import maskedarray as MA
+import maskedarray.core as MA
 #reload(MA)
 from maskedarray.core import MaskedArray, MAError, masked, nomask, \
     filled, getmask, getmaskarray, make_mask_none, mask_or, make_mask, \
@@ -56,8 +56,6 @@
 
 
 
-
-
 __all__ = [
 'TimeSeriesError','TimeSeriesCompatibilityError','TimeSeries','isTimeSeries',
 'time_series', 'tsmasked',
@@ -68,10 +66,10 @@
            ]
 
 #...............................................................................
+#
+#ufunc_domain = {}
+#ufunc_fills = {}
 
-ufunc_domain = {}
-ufunc_fills = {}
-
 #### --------------------------------------------------------------------------
 #--- ... TimeSeriesError class ...
 #### --------------------------------------------------------------------------
@@ -95,10 +93,11 @@
             msg = "Incompatible starting dates! (%s <> %s)"
         elif mode == 'size':
             msg = "Incompatible sizes! (%s <> %s)"
+        else:
+            msg = "Incompatibility !  (%s <> %s)"
         msg = msg % (first, second)
         TimeSeriesError.__init__(self, msg)
 
-
 #def _compatibilitycheck(a, b):
 def _timeseriescompat(a, b):
     """Checks the date compatibility of two TimeSeries object.
@@ -193,6 +192,61 @@
 ##### --------------------------------------------------------------------------
 ##--- ... Time Series ...
 ##### --------------------------------------------------------------------------
+class _tsmathmethod(object):
+    """Defines a wrapper for arithmetic array methods (add, mul...).
+When called, returns a new TimeSeries object, with the new series the result of
+the method applied on the original series.
+The `_dates` part remains unchanged.
+    """
+    def __init__ (self, methodname):
+        self._name = methodname
+    #
+    def __get__(self, obj, objtype=None):
+        "Gets the calling object."
+        self.obj = obj
+        return self
+    #
+    def __call__ (self, other, *args):
+        "Execute the call behavior."
+        instance = self.obj
+        if isinstance(other, TimeSeries):
+            assert(_timeseriescompat(instance, other))
+        func = getattr(super(TimeSeries, instance), self._name)
+        result = func(other, *args) #.view(type(instance))
+        result._dates = instance._dates
+        return result
+
+class _tsarraymethod(object):
+    """Defines a wrapper for basic array methods.
+When called, returns a new TimeSeries object, with the new series the result of
+the method applied on the original series.
+If `ondates` is True, the same operation is performed on the `_dates`.
+If `ondates` is False, the `_dates` part remains unchanged.
+    """
+    def __init__ (self, methodname, ondates=False):
+        """abfunc(fillx, filly) must be defined.
+           abinop(x, filly) = x for all x to enable reduce.
+        """
+        self._name = methodname
+        self._ondates = ondates
+    #
+    def __get__(self, obj, objtype=None):
+        self.obj = obj
+        return self
+    #
+    def __call__ (self, *args):
+        "Execute the call behavior."
+        _name = self._name
+        instance = self.obj
+        func_series = getattr(super(TimeSeries, instance), _name)
+        result = func_series(*args)
+        if self._ondates:
+            result._dates = getattr(instance._dates, _name)
+        else:
+            result._dates = instance._dates
+        return result
+
+
 class TimeSeries(MaskedArray, object):     
     """Base class for the definition of time series.
 A time series is here defined as the combination of three arrays:
@@ -207,120 +261,62 @@
 The combination of `series` and `dates` is the `data` part.
     """
     options = None
+    _defaultobserved = None
     def __new__(cls, data, dates=None, mask=nomask, 
                 freq=None, observed=None, start_date=None, 
                 dtype=None, copy=False, fill_value=None,
                 keep_mask=True, small_mask=True, hard_mask=False):
-        #tslog.info("__new__: received data types %s, %s" % (type(data), data))
         maparms = dict(copy=copy, dtype=dtype, fill_value=fill_value,
                        keep_mask=keep_mask, small_mask=small_mask, 
-                       hard_mask=hard_mask, )
-        if isinstance(data, TimeSeries):
-            # Check dates ........
-            if dates is None:
-                newdates = data._dates
-            else:
-                if not hasattr(dates,'freq'):
-                    raise DateError, "Invalid Dates!"       
-                newdates = dates
-                data._dates = newdates
-                if hasattr(data, '_data') and hasattr(data._data, '_dates'):
-                    data._data._dates = newdates
-            cls._defaultdates = newdates    
-            # Check frequency......
-            if freq is not None:
-                freq = corelib.check_freq(freq)
-                if freq != newdates.freq:
-                    _dates = newdates.tofreq(freq)
-            else:
-                freq = newdates.freq
-            # Check observed.......
-            if observed is None:
-                observed = data.observed
-            else:
-                observed = corelib.fmtObserv(observed)
-            cls._defaultobserved = observed  
-            _data = data._series
+                       hard_mask=hard_mask,)
+        # Get the data ...............................
+        _data = MaskedArray(data, mask=mask, **maparms).view(cls)
+        # Get the frequency ..........................
+        freq = corelib.check_freq(freq)
+        # Get the dates ..............................
+        if dates is None:
+            newdates = getattr(data, '_dates', None)
         else:
-            # Check dates ........
-            if dates is None:
-                length = _getdatalength(data)
-                if length > 0:
-                    newdates = date_array(start_date=start_date, length=length,
-                                          freq=freq)
-                else:
-                    newdates = date_array([], freq=freq)
-            elif not hasattr(dates, 'freq'):
+            newdates = dates
+        if newdates is not None:
+            if not hasattr(newdates, 'freq'):
                 newdates = date_array(dlist=dates, freq=freq)
+            if freq is not None and newdates.freq != freq:
+                newdates = newdates.tofreq(freq)
+        else:
+            length = _getdatalength(data)
+            if length > 0:
+                newdates = date_array(start_date=start_date, length=length,
+                                      freq=freq)
             else:
-                newdates = dates
-            # Check data .........
-            _data = data
-            if hasattr(data, '_mask') :
-                mask = mask_or(data._mask, mask)
-            # Set default ........
-            cls._defaultdates = newdates    
-            cls._defaultobserved = corelib.fmtObserv(observed)
-
+                newdates = date_array([], freq=freq)          
+        # Get observed ...............................
+        observed = getattr(data, 'observed', corelib.fmtObserv(observed))
+        
         if _data is masked:
             assert(numeric.size(newdates)==1)
             return _data.view(cls)
-        newdata = super(TimeSeries,cls).__new__(cls, _data, mask=mask,
-                                                **maparms)
-        assert(_datadatescompat(newdata._data,newdates))
-        return newdata
-            
-    #..................................
-    def __array_wrap__(self, obj, context=None):
-        return TimeSeries(super(TimeSeries,self).__array_wrap__(obj, context),
-                          dates=self._dates)
+        assert(_datadatescompat(_data,newdates))
+        _data._dates = newdates
+        _data._defaultdates = _data._dates
+        return _data
     #............................................
     def __array_finalize__(self,obj):
-        #tslog.info("__array_finalize__ received %s" % type(obj))      
-        if isinstance(obj, TimeSeries):
-            self._dates = obj._dates
-            self._data = obj._series._data
-            self._mask = obj._series._mask
-            self._series = obj._series
-            self._hardmask = obj._series._hardmask
-            self.observed = obj.observed
-            self._fill_value = obj._fill_value
-        else:     
-            self._dates = self._defaultdates
-            self.observed = self._defaultobserved
-            self._data = obj
-            self._mask = self._defaultmask
-            if obj is masked:
-                self._series = masked
-            else:
-                self._series = MA.array(obj, mask=self._defaultmask, 
-                                        copy=False, hard_mask=self._defaulthardmask)
-            self._hardmask = self._defaulthardmask
-            self.fill_value = self._fill_value
-        self._mask =  self._series._mask
-        self._data = self._series._data
-        self._hardmask = self._series._hardmask
-        #
-        TimeSeries._defaulthardmask = False
-        TimeSeries._defaultmask = nomask
-        #tslog.info("__array_finalize__ sends %s" % type(self))
+        MaskedArray.__array_finalize__(self, obj)        
+        self._dates = getattr(obj, '_dates', None)
+        self.observed = getattr(obj, 'observed', self._defaultobserved)
         return
+    #..................................
+    def __array_wrap__(self, obj, context=None):
+        result = super(TimeSeries, self).__array_wrap__(obj, context)
+        result._dates = self._dates
+        return result
     #............................................
-    def __getattribute__(self,attr):
-        "Returns a given attribute."
-        # Here, we need to be smart: _mask should call _series._mask...
-        if attr in ['_data','_mask','_hardmask']:
-            return getattr(self._series,attr)
-        return super(TimeSeries, self).__getattribute__(attr)
-    
-    def __setattribute__(self,attr, value):
-        """Sets an attribute to a given value."""
-        # Same thing here: if we modify ._mask, we need to modify _series._mask
-        # ...as well
-        super(TimeSeries, self).__setattribute__(attr, value)
-        if attr in ['_data','_mask','_hardmask']:
-            super(self._series.__class__, self._series).__setattribute__(attr, value)
-            setattr(self._series, attr, value)
+    def _get_series(self):
+        if self._mask.ndim == 0 and self._mask:
+            return masked
+        return self.view(MaskedArray)
+    _series = property(fget=_get_series)
     #............................................
     def __checkindex(self, indx):
         "Checks the validity of an index."
@@ -397,43 +393,25 @@
             raise MAError, 'Cannot alter the masked element.'
         (sindx, dindx) = self.__checkindex(indx)
         #....        
-        if value is tsmasked:
-            self._series[sindx] = masked
-        elif isinstance(value, TimeSeries):
-            assert(_timeseriescompat(self[sindx], value))
-            self._series[sindx] = value._series
-        else:
-            self._series[sindx] = value
-        # Don't forget to update the mask !
-        self._mask = self._series._mask
-        
+        super(TimeSeries, self).__setitem__(sindx, value)    
     #........................
     def __getslice__(self, i, j):
         "Gets slice described by i, j"
         (si,di) = self.__checkindex(i)
         (sj,dj) = self.__checkindex(j)
-        (data, date) = (self._series[si:sj], self._dates[di:dj])
-        return TimeSeries(data, dates=date, copy=False)
+        result = super(TimeSeries, self).__getitem__(slice(si,sj))
+        result._dates = self._dates[di:dj]
+        return result
     #....
     def __setslice__(self, i, j, value):
         "Gets item described by i. Not a copy as in previous versions."
-        (si,di) = self.__checkindex(i)
-        (sj,dj) = self.__checkindex(j)
+        (si,_) = self.__checkindex(i)
+        (sj,_) = self.__checkindex(j)
         #....
-#        data = self._series[i:j]
         if isinstance(value, TimeSeries):
             assert(_timeseriescompat(self[si:sj], value))
-            self._series[si:sj] = value._series
-        else:
-            self._series[si:sj] = value
-        # Don't forget to update the mask !
-        self._mask = self._series._mask
+        super(TimeSeries, self).__setitem__(slice(si,sj), value)
     #......................................................
-    def __len__(self):
-        if self.ndim == 0:
-            return 0
-        return ndarray.__len__(self)
-    #......................................................
     def __str__(self):
         """Returns a string representation of self (w/o the dates...)"""
         return str(self._series)
@@ -466,30 +444,46 @@
                        'time': timestr,
                        'freq': self.freqstr, }
     #............................................
-    def _get_mask(self):
-        """Returns the current mask."""
-        return self._series._mask
-    def _set_mask(self, mask):
-        """Sets the mask to `mask`."""
-        mask = make_mask(mask, copy=False, small_mask=True)
-        if mask is not nomask:
-            if mask.size != self._data.size:
-                raise ValueError, "Inconsistent shape between data and mask!"
-            if mask.shape != self._data.shape:
-                mask.shape = self._data.shape
-            self._series._mask = mask  
-        else:
-            self._series._mask = nomask
-    mask = property(fget=_get_mask, fset=_set_mask, doc="Mask")
- 
+    __add__ = _tsmathmethod('__add__')
+    __radd__ = _tsmathmethod('__add__')
+    __sub__ = _tsmathmethod('__sub__')
+    __rsub__ = _tsmathmethod('__rsub__')
+    __pow__ = _tsmathmethod('__pow__')
+    __mul__ = _tsmathmethod('__mul__')
+    __rmul__ = _tsmathmethod('__mul__')
+    __div__ = _tsmathmethod('__div__')
+    __rdiv__ = _tsmathmethod('__rdiv__')
+    __truediv__ = _tsmathmethod('__truediv__')
+    __rtruediv__ = _tsmathmethod('__rtruediv__')
+    __floordiv__ = _tsmathmethod('__floordiv__')
+    __rfloordiv__ = _tsmathmethod('__rfloordiv__')
+    __eq__ = _tsmathmethod('__eq__')
+    __ne__ = _tsmathmethod('__ne__')
+    __lt__ = _tsmathmethod('__lt__')
+    __le__ = _tsmathmethod('__le__')
+    __gt__ = _tsmathmethod('__gt__')
+    __ge__ = _tsmathmethod('__ge__')
+    
+    astype = _tsarraymethod('astype')
+    reshape = _tsarraymethod('reshape', ondates=True)
+    copy = _tsarraymethod('copy', ondates=True)
+    compress = _tsarraymethod('compress', ondates=True)
+    ravel = _tsarraymethod('ravel', ondates=True)
+    cumsum = _tsarraymethod('cumsum',ondates=False)
+    cumprod = _tsarraymethod('cumprod',ondates=False)
+    anom = _tsarraymethod('anom',ondates=False)
+    
+#    def nonzero(self):
+#        """Returns a tuple of ndarrays, one for each dimension of the array,
+#    containing the indices of the non-zero elements in that dimension."""
+#        return self._series.nonzero()
+    
+#    filled = _tsarraymethod('filled', ondates=False)
+    
+    #............................................ 
     def ids (self):
         """Return the ids of the data, dates and mask areas"""
-        return (id(self._series), id(self.dates),)
-        
-    def copy(self):
-        "Returns a copy of the TimeSeries."
-        return TimeSeries(self, copy=True)
-    
+        return (id(self._series), id(self.dates),)   
     #------------------------------------------------------
     @property
     def series(self):
@@ -507,7 +501,6 @@
     def freqstr(self):
         """Returns the corresponding frequency (as a string)."""
         return self._dates.freqstr
-        
     @property
     def day(self):          
         "Returns the day of month for each date in self._dates."
@@ -605,10 +598,6 @@
         "Converts the dates to another frequency, and adapt the data."
         return convert(self, freq, func=func, position=position)
     #.....................................................
-    def nonzero(self):
-        """Returns a tuple of ndarrays, one for each dimension of the array,
-    containing the indices of the non-zero elements in that dimension."""
-        return self._series.nonzero()
         
 def _attrib_dict(series, exclude=[]):
     """this function is used for passing through attributes of one
@@ -621,128 +610,7 @@
 ##### --------------------------------------------------------------------------
 ##--- ... Additional methods ...
 ##### --------------------------------------------------------------------------
-class _inplacemethod(object):
-    """Defines a wrapper for inplace arithmetic array methods (iadd, imul...).
-When called, returns a new TimeSeries object, with the new series the result of
-the method applied on the original series.
-The `_dates` part remains unchanged.
-    """
-    def __init__ (self, binop):
-        """abfunc(fillx, filly) must be defined.
-           abinop(x, filly) = x for all x to enable reduce.
-        """
-        self.f = binop
-        self.obj = None
-    #
-    def __get__(self, obj, objtype=None):
-        "Gets the calling object."
-        self.obj = obj
-        return self
-    #
-    def __call__ (self, other, *args):
-        "Execute the call behavior."
-        instance = self.obj
-        assert(_timeseriescompat(instance,other))
-        func = getattr(instance._series, self.f)    
-        func(other, *args)
-        return instance
-#......................................
-TimeSeries.__iadd__ = _inplacemethod('__iadd__')
-TimeSeries.__iand__ = _inplacemethod('__iand__')
-TimeSeries.__idiv__ = _inplacemethod('__idiv__')
-TimeSeries.__isub__ = _inplacemethod('__isub__')
-TimeSeries.__imul__ = _inplacemethod('__imul__')
 
-
-class _tsmathmethod(object):
-    """Defines a wrapper for arithmetic array methods (add, mul...).
-When called, returns a new TimeSeries object, with the new series the result of
-the method applied on the original series.
-The `_dates` part remains unchanged.
-    """
-    def __init__ (self, binop):
-        """abfunc(fillx, filly) must be defined.
-           abinop(x, filly) = x for all x to enable reduce.
-        """
-        self.f = binop
-    #
-    def __get__(self, obj, objtype=None):
-        "Gets the calling object."
-        self.obj = obj
-        return self
-    #
-    def __call__ (self, other, *args):
-        "Execute the call behavior."
-        instance = self.obj
-        _dates = instance._dates
-        #tslog.info("_tsmathmethod: series: %s" % instance,)
-        #tslog.info("_tsmathmethod: other  : %s" % other,)
-        func = getattr(instance._series, self.f)    
-        if isinstance(other, TimeSeries):
-            assert(_timeseriescompat(instance, other))
-        return instance.__class__(func(other, *args), dates=_dates,)
-#......................................
-TimeSeries.__add__ = _tsmathmethod('__add__')
-TimeSeries.__radd__ = _tsmathmethod('__add__')
-TimeSeries.__sub__ = _tsmathmethod('__sub__')
-TimeSeries.__rsub__ = _tsmathmethod('__rsub__')
-TimeSeries.__pow__ = _tsmathmethod('__pow__')
-TimeSeries.__mul__ = _tsmathmethod('__mul__')
-TimeSeries.__rmul__ = _tsmathmethod('__mul__')
-TimeSeries.__div__ = _tsmathmethod('__div__')
-TimeSeries.__rdiv__ = _tsmathmethod('__rdiv__')
-TimeSeries.__truediv__ = _tsmathmethod('__truediv__')
-TimeSeries.__rtruediv__ = _tsmathmethod('__rtruediv__')
-TimeSeries.__floordiv__ = _tsmathmethod('__floordiv__')
-TimeSeries.__rfloordiv__ = _tsmathmethod('__rfloordiv__')
-TimeSeries.__eq__ = _tsmathmethod('__eq__')
-TimeSeries.__ne__ = _tsmathmethod('__ne__')
-TimeSeries.__lt__ = _tsmathmethod('__lt__')
-TimeSeries.__le__ = _tsmathmethod('__le__')
-TimeSeries.__gt__ = _tsmathmethod('__gt__')
-TimeSeries.__ge__ = _tsmathmethod('__ge__')
-#................................................
-class _tsarraymethod(object):
-    """Defines a wrapper for basic array methods.
-When called, returns a new TimeSeries object, with the new series the result of
-the method applied on the original series.
-If `ondates` is True, the same operation is performed on the `_dates`.
-If `ondates` is False, the `_dates` part remains unchanged.
-    """
-    def __init__ (self, methodname, ondates=False):
-        """abfunc(fillx, filly) must be defined.
-           abinop(x, filly) = x for all x to enable reduce.
-        """
-        self._name = methodname
-        self._ondates = ondates
-    #
-    def __get__(self, obj, objtype=None):
-        self.obj = obj
-        return self
-    #
-    def __call__ (self, *args):
-        "Execute the call behavior."
-        _name = self._name
-        instance = self.obj
-        func_series = getattr(instance._series, _name)
-        if self._ondates:
-            func_dates = getattr(instance._dates, _name)
-            return instance.__class__(func_series(*args), 
-                                      dates=func_dates(*args))
-        else:
-            return instance.__class__(func_series(*args), 
-                                      dates=instance._dates)  
-TimeSeries.astype = _tsarraymethod('astype')
-TimeSeries.reshape = _tsarraymethod('reshape', ondates=True)
-TimeSeries.copy = _tsarraymethod('copy', ondates=True)
-TimeSeries.compress = _tsarraymethod('compress', ondates=True)
-TimeSeries.ravel = _tsarraymethod('ravel', ondates=True)
-TimeSeries.filled = _tsarraymethod('filled', ondates=False)
-TimeSeries.cumsum = _tsarraymethod('cumsum',ondates=False)
-TimeSeries.cumprod = _tsarraymethod('cumprod',ondates=False)
-TimeSeries.anom = _tsarraymethod('anom',ondates=False)
-
-#......................................
 class _tsaxismethod(object):
     """Defines a wrapper for array methods working on an axis (mean...).
 When called, returns a ndarray, as the result of the method applied on the series.
@@ -982,6 +850,7 @@
     `data` : 
         Array of data.
     """
+    data = numeric.asanyarray(data)
     if dates is None:
         length = _getdatalength(data)
         if length > 0:
@@ -1375,12 +1244,6 @@
     data = MA.asarray(data)
     newdatad = numeric.empty(nsize, data.dtype)
     newdatam = numeric.ones(nsize, bool_)
-#    if fill_value is None:
-#        if hasattr(data,'fill_value'):
-#            fill_value = data.fill_value
-#        else:
-#            fill_value = MA.default_fill_value(data)
-    #data = data.filled(fill_value)
     #....
     if datam is nomask:
         for (new,old) in zip(newslc,oldslc):
@@ -1448,19 +1311,6 @@
 if __name__ == '__main__':
     from maskedarray.testutils import assert_equal
     import numpy as N
+       
+
     
-    if 1:
-        #TODO: CHECK THAT, AND PUT IT IN tests/test_timeseries IF IT WORKS
-        # Test 2 points of 3 variables
-        xx = time_series([[1,2,3],[4,5,6]], start_date=thisday('b'))
-        assert_equal(xx[0]._data, [[1,2,3]])
-        assert_equal(xx[:,0]._data, [1,4])
-        # Test a single point of 3 variables
-        xx = time_series([[1,2,3]], start_date=thisday('b'))
-        assert_equal(xx[0]._data, [[1,2,3]])
-        assert_equal(xx[:,0]._data, [[1]])
-        # Test 3 data points
-        x = time_series([1,2,3], start_date=thisday('b'))
-        assert_equal(x[0], 1)
-        # Test using a DateArray as items
-        assert_equal(x[x._dates[:]],x)




More information about the Scipy-svn mailing list