[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