Source code for paws.core.operations.PROCESSING.SMOOTHING.SavitzkyGolay

from collections import OrderedDict

import numpy as np

from ... import Operation as opmod 
from ...Operation import Operation

inputs = OrderedDict(x=None,y=None,dy=None,order=None,base=None)
outputs = OrderedDict(smoothdata=None)

[docs]class SavitzkyGolay(Operation): """Applies a Savitzky-Golay polynomial smoothing filter to a 1d array.""" def __init__(self): super(SavitzkyGolay, self).__init__(inputs, outputs) self.input_doc['x'] = '1d array- independent variable' self.input_doc['y'] = '1d array- dependent variable, same shape as x' self.input_doc['dy'] = '1d array, error estimate in y, same shape as y (default None)' self.input_doc['order'] = 'integer order of polynomial approximation (zero to five)' self.input_doc['base'] = '-1, 0, or positive integer; see class docs' self.output_doc['smoothdata'] = 'smoothed 1d array for y'
[docs] def run(self): x = self.inputs['x'] y = self.inputs['y'] o = self.inputs['order'] b = self.inputs['base'] err = self.inputs['dy'] nx = x.size if err is None: err = np.ones(y.shape,dtype=float) # TODO: document what is being done here. # "Minimal" point base case. if b == -1: o_odd_flag = ((o/2)*2 != o) npts = o+1+int(o_odd_flag) # "Balanced" point base case. elif b == 0: npts = 2*o+1 # "Additional" point base case. elif b > 0: npts = 2*(o+b)+1 # TODO: build y_out in a list comprehension. y_out = np.zeros(nx, dtype=float) for i in range(nx): # choose start and end indices npts_half = int(npts)/2 + 1 start = max([i-npts_half+1,0]) end = min([i+npts_half-1,nx-1]) if b == -1: if (i-npts_half+1 < 0): start = 0 end = npts elif (i+npts_half-1 > nx-1): start = size-1-m end = size-1 # Formulate the equation to be solved for polynomial coefficients xvals = x[start:end] yvals = y[start:end] errvals = err[start:end] nxvals = xvals.size # TODO: document what is happening here idxs = np.arange(o+1) # reshape vectors for matrix mult y_vec = np.reshape(yvals,(nxvals,1,1)) x_vec = np.reshape(xvals,(nxvals,1,1)) err_vec = np.reshape(errvals,(nxvals,1,1)) idx_column = np.reshape(idxs,(nxvals,1)) idx_row = np.reshape(idxs,(1,nxvals)) idx_block = idx_row + idx_column v = (y_vec * x_vec ** idx_column * err_vec).sum(axis=0) m = (x_vec ** idx_block * err_vec).sum(axis=0) # CALL LINALG.SOLVE... coefs = (np.linalg.solve(m, v)).flatten() y_out[i] = np.sum(x[i]**np.arange(o+1)*coefs) self.outputs['smoothdata'] = y_out