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

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


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

Added:
   trunk/Lib/sandbox/timeseries/addons/
   trunk/Lib/sandbox/timeseries/addons/__init__.py
   trunk/Lib/sandbox/timeseries/addons/filters.py
   trunk/Lib/sandbox/timeseries/addons/interpolate.py
   trunk/Lib/sandbox/timeseries/addons/tests/
   trunk/Lib/sandbox/timeseries/addons/tests/test_filters.py
   trunk/Lib/sandbox/timeseries/addons/tests/test_interpolate.py
Log:
extras : deleted, redispatched to addons/filters and addons/interpolate

Added: trunk/Lib/sandbox/timeseries/addons/__init__.py
===================================================================
--- trunk/Lib/sandbox/timeseries/addons/__init__.py	2007-03-01 22:38:43 UTC (rev 2806)
+++ trunk/Lib/sandbox/timeseries/addons/__init__.py	2007-03-02 08:48:04 UTC (rev 2807)
@@ -0,0 +1,9 @@
+"""
+:author: Pierre GF Gerard-Marchant & Matt Knox
+:contact: pierregm_at_uga_dot_edu - mattknox_ca_at_hotmail_dot_com
+:version: $Id$
+"""
+__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author$)"
+__version__ = '1.0'
+__revision__ = "$Revision$"
+__date__     = '$Date$'
\ No newline at end of file


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

Added: trunk/Lib/sandbox/timeseries/addons/filters.py
===================================================================
--- trunk/Lib/sandbox/timeseries/addons/filters.py	2007-03-01 22:38:43 UTC (rev 2806)
+++ trunk/Lib/sandbox/timeseries/addons/filters.py	2007-03-02 08:48:04 UTC (rev 2807)
@@ -0,0 +1,137 @@
+"""
+
+A collection of filters for timeseries
+
+:author: Pierre GF Gerard-Marchant & Matt Knox
+:contact: pierregm_at_uga_dot_edu - mattknox_ca_at_hotmail_dot_com
+:version: $Id$
+"""
+__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author$)"
+__version__ = '1.0'
+__revision__ = "$Revision$"
+__date__     = '$Date$'
+
+import numpy as N
+from numpy import bool_, float_
+narray = N.array
+
+from scipy.signal import convolve, get_window
+
+import maskedarray as MA
+from maskedarray import MaskedArray, nomask, getmask, getmaskarray, masked
+marray = MA.array
+
+
+__all__ = ['expmave'
+           'running_window', 'running_mean'           
+           ]
+
+#####---------------------------------------------------------------------------
+#---- --- Moving average functions ---
+#####---------------------------------------------------------------------------
+def expmave(data, n, tol=1e-6):
+    """Calculate the exponential moving average of a series.
+
+:Parameters:
+    - `data` (ndarray, MaskedArray) : data is a valid ndarray or MaskedArray
+      or an instance of a subclass of these types. In particular, TimeSeries
+      objects are valid here.
+    - `n` (int) : time periods. Where the smoothing factor is 2/(n + 1)
+    - `tol` (float, *[1e-6]*) : when `data` contains masked values, this
+      parameter will determine what points in the result should be masked.
+      Values in the result that would not be "significantly" impacted (as
+      determined by this parameter) by the masked values are left unmasked.
+"""
+    if isinstance(data, MaskedArray):
+        ismasked = (data._mask is not nomask)
+    else:
+        ismasked = False
+    #
+    k = 2./float(n + 1)
+    def expmave_sub(a, b):
+        return b + k * (a - b)
+    #    
+    if ismasked:
+        data = data.filled(0)
+    #
+    result = N.frompyfunc(expmave_sub, 2, 1).accumulate(data).astype(data.dtype)
+    if ismasked:
+        _unmasked = N.logical_not(getmask(data)).astype(float_)
+        marker = 1 - N.frompyfunc(expmave_sub, 2, 1).accumulate(_unmasked)
+        result[marker > tol] = masked
+    #
+    return result
+
+#...............................................................................
+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
+        is applied recursively on each column.
+    window_type : string/tuple/float
+        Window type (see Notes)
+    window_size : integer
+        The width of the window.
+        
+Notes
+-----
+
+The recognized window types are: boxcar, triang, blackman, hamming, hanning, 
+bartlett, parzen, bohman, blackmanharris, nuttall, barthann, kaiser (needs beta), 
+gaussian (needs std), general_gaussian (needs power, width), slepian (needs width).
+If the window requires parameters, the window_type argument should be a tuple
+with the first argument the string name of the window, and the next arguments 
+the needed parameters. If window_type is a floating point number, it is interpreted 
+as the beta parameter of the kaiser window.
+
+Note also that only boxcar has been thoroughly tested.
+    """
+    #
+    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, 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:
+        for i in range(data.shape[-1]):
+            _data = data._data[:,i]
+            _data.flat = convolve(_data, window)[k:n+k] / float(window_size)
+            data._mask[:,i] = (convolve(data._mask[:,i], window) > 0)[k:n+k]
+    else:
+        raise ValueError, "Data should be at most 2D"
+    data._mask[:k] = data._mask[-k:] = True
+    return data
+
+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.    
+    """
+    return running_window(data, 'boxcar', width)
+
+################################################################################
+if __name__ == '__main__':
+    from maskedarray.testutils import assert_equal, assert_almost_equal
+    from timeseries import time_series, thisday
+    


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

Added: trunk/Lib/sandbox/timeseries/addons/interpolate.py
===================================================================
--- trunk/Lib/sandbox/timeseries/addons/interpolate.py	2007-03-01 22:38:43 UTC (rev 2806)
+++ trunk/Lib/sandbox/timeseries/addons/interpolate.py	2007-03-02 08:48:04 UTC (rev 2807)
@@ -0,0 +1,115 @@
+"""
+A collection of intperolation tools for timeseries
+
+:author: Pierre GF Gerard-Marchant & Matt Knox
+:contact: pierregm_at_uga_dot_edu - mattknox_ca_at_hotmail_dot_com
+:version: $Id$
+"""
+__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author$)"
+__version__ = '1.0'
+__revision__ = "$Revision$"
+__date__     = '$Date$'
+
+
+import numpy.core.numeric as numeric
+
+from scipy.interpolate import fitpack
+
+import maskedarray as MA
+from maskedarray.core import masked, nomask, getmask
+from maskedarray.extras import flatnotmasked_edges
+marray = MA.array
+
+
+__all__ = [
+    'forward_fill', 'backward_fill', 'interp_masked1d',
+          ]
+
+
+
+
+#####---------------------------------------------------------------------------
+#---- --- Functions for filling in masked values in a masked array ---
+#####---------------------------------------------------------------------------
+def forward_fill(marr, maxgap=None):
+    """forward_fill(marr, maxgap=None)
+
+Forward fills masked values in a 1-d array when there are less maxgap
+consecutive masked values. If maxgap is None, then forward fill all
+masked values."""
+    # Initialization ..................
+    if numeric.ndim(marr) > 1:
+        raise ValueError,"The input array should be 1D only!"
+    marr = marray(marr, copy=True)
+    if getmask(marr) is nomask or marr.size == 0:
+        return marr
+    #
+    currGap = 0
+    if maxgap is not None:
+        for i in range(1, marr.size):
+            if marr._mask[i]:
+                currGap += 1
+                if currGap <= maxgap and not marr._mask[i-1]:
+                    marr._data[i] = marr._data[i-1]
+                    marr._mask[i] = False
+                elif currGap == maxgap + 1:
+                    marr._mask[i-maxgap:i] = True
+            else:
+                currGap = 0               
+    else:
+        for i in range(1, marr.size):
+            # CHECK: We should probable be able to speed things up here
+            if marr._mask[i] and not marr._mask[i-1]:
+                marr._data[i] = marr._data[i-1]
+                marr._mask[i] = False
+    return marr
+#..........................................................
+def backward_fill(marr, maxgap=None):
+    """backward_fill(marr, maxgap=None)
+
+Backward fills masked values in a 1-d array when there are less than maxgap
+consecutive masked values. If maxgap is None, then backward fills all
+masked values.
+    """
+    return forward_fill(marr[::-1], maxgap=maxgap)[::-1]
+
+#..........................................................
+def interp_masked1d(marr, kind='linear'):
+    """interp_masked1d(marr, king='linear')
+
+Interpolates masked values in marr according to method kind.
+kind must be one of 'constant', 'linear', 'cubic', quintic'
+"""
+    if numeric.ndim(marr) > 1: 
+        raise ValueError("array must be 1 dimensional!")
+    #
+    marr = marray(marr, copy=True)
+    if getmask(marr) is nomask: 
+        return marr
+    #
+    unmaskedIndices = (~marr._mask).nonzero()[0]
+    if unmaskedIndices.size < 2: 
+        return marr
+    #    
+    kind = kind.lower()
+    if kind == 'constant': 
+        return forward_fill(marr)
+    try:
+        k = {'linear' : 1,
+             'cubic' : 3,
+             'quintic' : 5}[kind.lower()]
+    except KeyError:
+        raise ValueError("Unsupported interpolation type.")
+    
+    first_unmasked, last_unmasked = flatnotmasked_edges(marr)
+    
+    vals = marr.data[unmaskedIndices]
+    
+    tck = fitpack.splrep(unmaskedIndices, vals, k=k)
+    
+    maskedIndices = marr._mask.nonzero()[0]
+    interpIndices = maskedIndices[(maskedIndices > first_unmasked) & \
+                                  (maskedIndices < last_unmasked)]
+    marr[interpIndices] = fitpack.splev(interpIndices, tck).astype(marr.dtype)
+    return marr
+


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

Added: trunk/Lib/sandbox/timeseries/addons/tests/test_filters.py
===================================================================
--- trunk/Lib/sandbox/timeseries/addons/tests/test_filters.py	2007-03-01 22:38:43 UTC (rev 2806)
+++ trunk/Lib/sandbox/timeseries/addons/tests/test_filters.py	2007-03-02 08:48:04 UTC (rev 2807)
@@ -0,0 +1,90 @@
+# pylint: disable-msg=W0611, W0612, W0511,R0201
+"""Tests suite for MaskedArray & subclassing.
+
+:author: Pierre Gerard-Marchant & Matt Knox
+:contact: pierregm_at_uga_dot_edu & mattknox_ca_at_hotmail_dot_com
+:version: $Id$
+"""
+__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author$)"
+__version__ = '1.0'
+__revision__ = "$Revision$"
+__date__     = '$Date$'
+
+import numpy as N
+import numpy.core.numeric as numeric
+
+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
+
+
+class test_runningmean(NumpyTestCase):
+    
+    def __init__(self, *args, **kwds):
+        NumpyTestCase.__init__(self, *args, **kwds)
+        self.data = numeric.arange(25)
+        self.maskeddata = MaskedArray(self.data)
+        self.maskeddata[10] = masked
+    #         
+    def test_onregulararray(self):
+        data = self.data
+        for width in [3,5,7]:
+            k = (width-1)/2
+            ravg = running_mean(data,width)
+            assert(isinstance(ravg, MaskedArray))
+            assert_equal(ravg, data)
+            assert_equal(ravg._mask, [1]*k+[0]*(len(data)-2*k)+[1]*k)
+    #
+    def test_onmaskedarray(self):
+        data = self.maskeddata
+        for width in [3,5,7]:
+            k = (width-1)/2
+            ravg = running_mean(data,width)
+            assert(isinstance(ravg, MaskedArray))
+            assert_equal(ravg, data)
+            m = N.zeros(len(data), N.bool_)
+            m[:k] = m[-k:] = m[10-k:10+k+1] = True
+            assert_equal(ravg._mask, m)
+    #
+    def test_ontimeseries(self):
+        data = time_series(self.maskeddata, start_date=thisday('D'))
+        for width in [3,5,7]:
+            k = (width-1)/2
+            ravg = running_mean(data,width)
+            assert(isinstance(ravg, MaskedArray))
+            assert_equal(ravg, data)
+            m = N.zeros(len(data), N.bool_)
+            m[:k] = m[-k:] = m[10-k:10+k+1] = True
+            assert_equal(ravg._mask, m)
+            assert_equal(ravg._dates, data._dates)
+    #
+    def tests_onmultitimeseries(self):
+        maskeddata = MaskedArray(N.random.random(75).reshape(25,3))
+        maskeddata[10] = masked
+        data = time_series(maskeddata, start_date=thisday('D'))
+        for width in [3,5,7]:
+            k = (width-1)/2
+            ravg = running_mean(data,width)
+            assert(isinstance(ravg, MaskedArray))
+            assert_almost_equal(ravg[18].squeeze(), data[18-k:18+k+1].mean(0))
+            m = N.zeros(data.shape, N.bool_)
+            m[:k] = m[-k:] = m[10-k:10+k+1] = True
+            assert_equal(ravg._mask, m)
+            assert_equal(ravg._dates, data._dates)
+
+#------------------------------------------------------------------------------
+if __name__ == "__main__":
+    NumpyTest().run()                
\ No newline at end of file


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

Added: trunk/Lib/sandbox/timeseries/addons/tests/test_interpolate.py
===================================================================
--- trunk/Lib/sandbox/timeseries/addons/tests/test_interpolate.py	2007-03-01 22:38:43 UTC (rev 2806)
+++ trunk/Lib/sandbox/timeseries/addons/tests/test_interpolate.py	2007-03-02 08:48:04 UTC (rev 2807)
@@ -0,0 +1,66 @@
+"""
+:author: Pierre Gerard-Marchant & Matt Knox
+:contact: pierregm_at_uga_dot_edu & mattknox_ca_at_hotmail_dot_com
+:version: $Id$
+"""
+__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author$)"
+__version__ = '1.0'
+__revision__ = "$Revision$"
+__date__     = '$Date$'
+
+import numpy as N
+import numpy.core.numeric as numeric
+
+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
+
+class test_funcs(NumpyTestCase):
+    
+    def __init__(self, *args, **kwds):
+        NumpyTestCase.__init__(self, *args, **kwds)
+        self.mask = [1,0,1,0,0,1,1,0,0,0]
+        self.data = numeric.arange(10)
+        self.test_array = masked_array(self.data, mask=self.mask)
+
+    def test_backward_fill (self):
+        result = masked_array(self.data, mask=self.mask)
+        result[0] = 1
+        result[2] = 3
+       
+        assert_equal(backward_fill(self.test_array, maxgap=1), result)
+        
+        result[5] = 7
+        result[6] = 7
+        
+        assert_equal(backward_fill(self.test_array), result)
+
+    def test_forward_fill (self):
+        result = masked_array(self.data, mask=self.mask)
+        result[2] = 1
+       
+        assert_equal(forward_fill(self.test_array, maxgap=1), result)
+        
+        result[5] = 4
+        result[6] = 4
+        
+        assert_equal(forward_fill(self.test_array), result)
+
+    def test_interp_fill(self):
+        result_lin = masked_array(self.data).astype(float_)
+        result_lin[0] = masked
+        
+        approx(interp_masked1d(self.test_array.astype(float_), kind='linear'), result_lin)
+        
+###############################################################################
+#------------------------------------------------------------------------------
+if __name__ == "__main__":
+    NumpyTest().run()              
\ No newline at end of file


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




More information about the Scipy-svn mailing list