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

scipy-svn at scipy.org scipy-svn at scipy.org
Sun Feb 25 21:55:03 EST 2007


Author: pierregm
Date: 2007-02-25 20:54:59 -0600 (Sun, 25 Feb 2007)
New Revision: 2760

Modified:
   trunk/Lib/sandbox/timeseries/__init__.py
   trunk/Lib/sandbox/timeseries/tdates.py
   trunk/Lib/sandbox/timeseries/tseries.py
Log:
tseries : forced a singleton to have a DateArray _dates
        : added empty_like, where dates are copied from the model
tdates  : reset the default freq to -9999 in DateArray.__array_finalize__
		: DateArray: put the cached info in a single directory '_cachedinfo'
		: fixed illegal propagation of cachedinfo
		: made freqstr a property
__init__: added import plotlib



Modified: trunk/Lib/sandbox/timeseries/__init__.py
===================================================================
--- trunk/Lib/sandbox/timeseries/__init__.py	2007-02-23 21:20:19 UTC (rev 2759)
+++ trunk/Lib/sandbox/timeseries/__init__.py	2007-02-26 02:54:59 UTC (rev 2760)
@@ -22,7 +22,8 @@
 import tmulti
 from tmulti import *
 import reportlib
-from reportlib import *
+from reportlib import *
+import plotlib
 
 __all__ = ['tdates', 'tseries','tmulti','reportlib']
 __all__ += tdates.__all__

Modified: trunk/Lib/sandbox/timeseries/tdates.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tdates.py	2007-02-23 21:20:19 UTC (rev 2759)
+++ trunk/Lib/sandbox/timeseries/tdates.py	2007-02-26 02:54:59 UTC (rev 2760)
@@ -550,7 +550,8 @@
 >>> for d in DateArray(...):
 accesses the array element by element. Therefore, `d` is a Date object.    
     """
-    (_tostr, _toord, _steps) = (None, None, None)
+    _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:
@@ -573,11 +574,11 @@
             raise ArithmeticDateError, "(function %s)" % context[0].__name__
     
     def __array_finalize__(self, obj):
-        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))
+        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):
@@ -598,6 +599,10 @@
             # behaviour
             return Date(self.freq, value=r.item())
         else:
+            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):
@@ -615,6 +620,10 @@
     __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')
@@ -667,7 +676,9 @@
     weeks = week
     
     def __getdateinfo__(self, info):
-        return numeric.asarray(cseries.getDateInfo(numeric.asarray(self), self.freq, info), dtype=int_)
+        return numeric.asarray(cseries.getDateInfo(numeric.asarray(self), 
+                                                   self.freq, info), 
+                               dtype=int_)
     __getDateInfo = __getdateinfo__    
     #.... Conversion methods ....................
     #
@@ -678,17 +689,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._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._toord = toord
-        return self._toord
+            self._cachedinfo['toord'] = toord
+        return self._cachedinfo['toord']
     #
     def tostring(self):
         "Converts the dates to strings."
         # Note: we better cache the result
-        if self._tostr is None:
+        if self._cachedinfo['tostr'] is None:
             firststr = str(self[0])
             if self.size > 0:
                 ncharsize = len(firststr)
@@ -696,8 +707,8 @@
                                         dtype='|S%i' % ncharsize)
             else:
                 tostr = firststr
-            self._tostr = tostr
-        return self._tostr
+            self._cachedinfo['tostr'] = tostr
+        return self._cachedinfo['tostr']
     #   
     def asfreq(self, freq=None, relation="BEFORE"):
         "Converts the dates to another frequency."
@@ -743,38 +754,39 @@
     The timesteps have the same unit as the frequency of the series."""
         if self.freq == 'U':
             warnings.warn("Undefined frequency: assuming integers!")
-        if self._steps is None:
+        if self._cachedinfo['steps'] is None:
+            _cached = self._cachedinfo
             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 _cached['full'] is None:
+                    _cached['full'] = (steps.max() == 1)
+                if _cached['hasdups'] is None:
+                    _cached['hasdups'] = (steps.min() == 0)
             else:
-                self._full = True
-                self._hasdups = False
+                _cached['full'] = True
+                _cached['hasdups'] = False
                 steps = numeric.array([], dtype=int_)
-            self._steps = steps
-        return self._steps
+            self._cachedinfo['steps'] = steps
+        return self._cachedinfo['steps']
     
     def has_missing_dates(self):
         "Returns whether the DateArray have missing dates."
-        if self._full is None:
+        if self._cachedinfo['full'] is None:
             steps = self.get_steps()
-        return not(self._full)
+        return not(self._cachedinfo['full'])
     
     def isfull(self):
         "Returns whether the DateArray has no missing dates."
-        if self._full is None:
+        if self._cachedinfo['full'] is None:
             steps = self.get_steps()
-        return self._full
+        return self._cachedinfo['full']
     
     def has_duplicated_dates(self):
         "Returns whether the DateArray has duplicated dates."
-        if self._hasdups is None:
+        if self._cachedinfo['hasdups'] is None:
             steps = self.get_steps()
-        return self._hasdups
+        return self._cachedinfo['hasdups']
     
     def isvalid(self):
         "Returns whether the DateArray is valid: no missing/duplicated dates."
@@ -996,6 +1008,7 @@
 ################################################################################
 
 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)]
@@ -1019,4 +1032,11 @@
             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

Modified: trunk/Lib/sandbox/timeseries/tseries.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tseries.py	2007-02-23 21:20:19 UTC (rev 2759)
+++ trunk/Lib/sandbox/timeseries/tseries.py	2007-02-26 02:54:59 UTC (rev 2760)
@@ -291,7 +291,7 @@
     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):
+                keep_mask=True, small_mask=True, hard_mask=False, **options):
         maparms = dict(copy=copy, dtype=dtype, fill_value=fill_value,
                        keep_mask=keep_mask, small_mask=small_mask, 
                        hard_mask=hard_mask,)
@@ -394,6 +394,7 @@
         m = self._mask
         singlepoint = (len(numeric.shape(newdate))==0)
         if singlepoint:
+            newdate = DateArray(newdate)
             if newdata is masked:
                 newdata = tsmasked
                 newdata._dates = newdate
@@ -655,20 +656,36 @@
         return convert(self, freq, func=func, position=position)
     #.....................................................
     def transpose(self, *axes):
+        """ a.transpose(*axes)
+
+    Returns a view of 'a' with axes transposed. If no axes are given,
+    or None is passed, switches the order of the axes. For a 2-d
+    array, this is the usual matrix transpose. If axes are given,
+    they describe how the axes are permuted.
+
+        """
         if self._dates.size == self.size:
             result = super(TimeSeries, self).transpose(*axes)
             result._dates = self._dates.transpose(*axes)
         else:
             errmsg = "Operation not permitted on multi-variable series"
-            print "AXES:",axes
             if (len(axes)==0) or axes[0] != 0:
-                raise ValueError, errmsg
+                raise TimeSeriesError, errmsg
             else:
                 result = super(TimeSeries, self).transpose(*axes)
                 result._dates = self._dates
         return result
+    #......................................................
+    def copy_attributes(self, oldseries, exclude=[]):
+        "Copies the attributes from oldseries if they are not in the exclude list."
+        attrlist = ['fill_value', 'observed']
+        if not isinstance(oldseries, TimeSeries):
+            msg = "Series should be a valid TimeSeries object! (got <%s> instead)"
+            raise TimeSeriesError, msg % type(oldseries)
+        for attr in attrlist:
+            if not attr in exclude:
+                setattr(self, attr, getattr(oldseries, attr))
     
-    
         
 def _attrib_dict(series, exclude=[]):
     """this function is used for passing through attributes of one
@@ -676,7 +693,7 @@
     result = {'fill_value':series.fill_value,
               'observed':series.observed}
     return dict(filter(lambda x: x[0] not in exclude, result.iteritems()))
-    
+  
         
 ##### --------------------------------------------------------------------------
 ##--- ... Additional methods ...
@@ -1061,14 +1078,14 @@
     newshape[0] = len(newdates)
     newshape = tuple(newshape)
     
-    newdata = masked_array(numeric.empty(newshape, dtype=a.dtype), mask=True)
-    #backup the series attributes
-    options = dict(fill_value=a.fill_value, observed=a.observed)
-    newseries = TimeSeries(newdata, newdates, **options)
+    newseries = numeric.empty(newshape, dtype=a.dtype).view(type(a))
+    newseries.__setmask__(numeric.ones(newseries.shape, dtype=bool_))
+    newseries._dates = newdates
     if dstart is not None:
         start_date = max(start_date, dstart)
         end_date = min(end_date, dend) + 1
         newseries[start_date:end_date] = a[start_date:end_date]
+    newseries.copy_attributes(a)
     return newseries
 #....................................................................
 def align_series(*series, **kwargs):
@@ -1105,7 +1122,7 @@
 aligned = align_series
 #....................................................................
 def convert(series, freq, func='auto', position='END'):
-    """Converts a series to a frequency
+    """Converts a series to a frequency.
        
     When converting to a lower frequency, func is a function that acts
     on a 1-d array and returns a scalar or 1-d array. func should handle
@@ -1156,12 +1173,20 @@
 
     if tempData.ndim == 2 and func is not None:
         tempData = MA.apply_along_axis(func, -1, tempData)
-           
-    newseries = TimeSeries(tempData, freq=toFreq, 
-                           observed=series.observed, 
-                           start_date=start_date)
+
+    newseries = tempData.view(type(series))
+    newseries._dates = date_array(start_date=start_date, length=len(newseries),
+                                  freq=toFreq)
+    newseries.copy_attributes(series)
     return newseries
+
+def group_byperiod(series, freq, func='auto', position='END'):
+    """Converts a series to a frequency, without any processing.
+    """
+    return convert(series, freq, func=None, position='END')
+
 TimeSeries.convert = convert
+TimeSeries.group_byperiod = group_byperiod
 
 #...............................................................................
 def tshift(series, nper, copy=True):
@@ -1207,7 +1232,9 @@
         newdata[:-nper] = inidata[nper:]
     else:
         newdata = inidata
-    newseries = TimeSeries(newdata, series._dates, **options)
+    newseries = newdata.view(type(series))
+    newseries._dates = series._dates
+    newseries.copy_attributes(series)
     return newseries
 TimeSeries.tshift = tshift
 #...............................................................................
@@ -1339,7 +1366,12 @@
     else:
         newdata[~keeper] = 0
     return newseries
-                           
+#...............................................................................
+def empty_like(series):
+    result = N.empty_like(series).view(type(series))
+    result._dates = series._dates
+    result._mask = series._mask
+    return result                           
     
 ################################################################################
 if __name__ == '__main__':
@@ -1361,13 +1393,21 @@
         sertrans = serfolded.transpose()
         assert_equal(sertrans.shape, (2,5))
         
-        assert ser1d[0] is tsmasked
-        print "OK"
     if 1:
         hodie = today('D')
         ser2d = time_series(N.arange(10).reshape(5,2), start_date=hodie,
                             mask=[[1,1],[0,0],[0,0],[0,0],[0,0]])
+        try:
+            ser2d_transpose = ser2d.transpose()
+        except TimeSeriesError:
+            pass
     if 1:
         hodie = today('D')
         ser3d = time_series(N.arange(30).reshape(5,3,2), start_date=hodie,)
+        try:
+            ser3d_transpose = ser3d.transpose()
+        except TimeSeriesError:
+            pass
+        assert_equal(ser3d.transpose(0,2,1).shape, (5,2,3))
+        
     




More information about the Scipy-svn mailing list