savitzky.py
Go to the documentation of this file.
00001 import numpy as np
00002 from math import factorial
00003 import pylab
00004 
00005 class savitzky_golay():
00006     r"""Smooth (and optionally differentiate) data with a Savitzky-Golay filter.
00007     The Savitzky-Golay filter removes high frequency noise from data.
00008     It has the advantage of preserving the original shape and
00009     features of the signal better than other types of filtering
00010     approaches, such as moving averages techniques.
00011     Parameters
00012     ----------
00013     y : array_like, shape (N,)
00014         the values of the time history of the signal.
00015     window_size : int
00016         the length of the window. Must be an odd integer number.
00017     order : int
00018         the order of the polynomial used in the filtering.
00019         Must be less then `window_size` - 1.
00020     deriv: int
00021         the order of the derivative to compute (default = 0 means only smoothing)
00022     Returns
00023     -------
00024     ys : ndarray, shape (N)
00025         the smoothed signal (or it's n-th derivative).
00026     Notes
00027     -----
00028     The Savitzky-Golay is a type of low-pass filter, particularly
00029     suited for smoothing noisy data. The main idea behind this
00030     approach is to make for each point a least-square fit with a
00031     polynomial of high order over a odd-sized window centered at
00032     the point.
00033     Examples
00034     --------
00035     t = np.linspace(-4, 4, 500)
00036     y = np.exp( -t**2 ) + np.random.normal(0, 0.05, t.shape)
00037     ysg = savitzky_golay(y, window_size=31, order=4)
00038     import matplotlib.pyplot as plt
00039     plt.plot(t, y, label='Noisy signal')
00040     plt.plot(t, np.exp(-t**2), 'k', lw=1.5, label='Original signal')
00041     plt.plot(t, ysg, 'r', label='Filtered signal')
00042     plt.legend()
00043     plt.show()
00044     References
00045     ----------
00046     .. [1] A. Savitzky, M. J. E. Golay, Smoothing and Differentiation of
00047        Data by Simplified Least Squares Procedures. Analytical
00048        Chemistry, 1964, 36 (8), pp 1627-1639.
00049     .. [2] Numerical Recipes 3rd Edition: The Art of Scientific Computing
00050        W.H. Press, S.A. Teukolsky, W.T. Vetterling, B.P. Flannery
00051        Cambridge University Press ISBN-13: 9780521880688
00052     """
00053 
00054     def __init__(self, window_size, order, deriv=0, rate=1):
00055 
00056         self.window_size = window_size
00057         self.order = order
00058         self.deriv = deriv
00059         self.rate = rate
00060 
00061         try:
00062             self.window_size = np.abs(np.int(self.window_size))
00063             self.order = np.abs(np.int(self.order))
00064         except ValueError, msg:
00065             raise ValueError("window_size and order have to be of type int")
00066         if self.window_size % 2 != 1 or self.window_size < 1:
00067             raise TypeError("window_size size must be a positive odd number")
00068         if self.window_size < self.order + 2:
00069             raise TypeError("window_size is too small for the polynomials order")
00070 
00071     def filter(self, y):
00072 
00073         self.order_range = range(self.order+1)
00074         half_window = (self.window_size -1) // 2
00075         # precompute coefficients
00076         b = np.mat([[k**i for i in self.order_range] for k in range(-half_window, half_window+1)])
00077         m = np.linalg.pinv(b).A[self.deriv] * self.rate**self.deriv * factorial(self.deriv)
00078         # pad the signal at the extremes with
00079         # values taken from the signal itself
00080         firstvals = y[0] - np.abs( y[1:half_window+1][::-1] - y[0] )
00081         lastvals = y[-1] + np.abs(y[-half_window-1:-1][::-1] - y[-1])
00082         y = np.concatenate((firstvals, y, lastvals))
00083         return np.convolve( m[::-1], y, mode='valid')
00084 
00085 if __name__ == "__main__":
00086 
00087     # create some sample twoD data
00088     x = np.linspace(-3,3,100)
00089     Z = np.exp( -(x))
00090 
00091     # add noise
00092     Zn = Z + np.random.normal( 0, 0.2, Z.shape )
00093 
00094     sg = savitzky_golay(window_size=29, order=4)
00095 
00096     l = sg.filter(Zn)
00097 
00098     pylab.plot(l)
00099 
00100     pylab.plot(Zn)
00101 
00102     pylab.show()


cob_voltage_control
Author(s): Alexander Bubeck
autogenerated on Thu Aug 27 2015 12:45:45