Savitzky-Golay derivatives, computed with SciPy's signal.savgol_filter need to be scaled?

2.9k Views Asked by At

I'm computing the first and second derivatives of a signal and then plot. I chose the Savitzky-Golay filter as implemented in SciPy (signal module). I'm wondering if the output needs to be scaled - in the Matlab implementation of the same filter, it is specified that scaling is needed on the output of the filter:

savitzkyGolayFilt(X,N,DN,F) filters the signal X using a Savitzky-Golay (polynomial) filter. The polynomial order, N, must be less than the frame size, F, and F must be odd. DN specifies the differentiation order (DN=0 is smoothing). For a DN higher than zero, you'll have to scale the output by 1/T^DN to acquire the DNth smoothed derivative of input X, where T is the sampling interval.

However, I didn't find anything similar in SciPy's documentation. Has anybody tried and knows if the output in Python is correct and needs no further scaling? The line of code I'm running for the first derivative is this one: first_deriv = signal.savgol_filter(spectra_signal,sigma=7,2, deriv=1, delta=3.1966) The spectra_signal is my "y" variable and delta is the variation of "x" variable.

Also, I tried to compute the first derivative without using the savgol_filter, but using np.diffon the smoothed signal instead (based on the formula derivative = dy/dx).first_deriv_alternative = np.diff(signal.savgol_filter(spectra_signal, sigma=7,2))/3.1966. And the results are not the same.

Working code example:

import numpy as np
from scipy import signal

x =[405.369888, 408.561553, 411.753217, 414.944882, 418.136547, 421.328212, 424.519877, 427.711541, 430.903206]
y =[5.001440644264221191e-01,
    4.990128874778747559e-01,
    4.994551539421081543e-01,
    5.002806782722473145e-01,
    5.027571320533752441e-01,
    5.053851008415222168e-01,
    5.082427263259887695e-01,
    5.122825503349304199e-01,
    5.167465806007385254e-01]

#variation of x variable, constant step 
sampling_step = x[1]-x[0] 
#Method 1: using savgol_filter
deriv1_method1 = signal.savgol_filter(y,5,2,deriv=1, delta=sampling_step)

#Method 2: using np.diff to compute the derivative of the filtered original data
dy=np.diff(signal.savgol_filter(y, 5,2))
dx=np.diff(x)
deriv1_method2=dy/dx

#Method 3: filtering the first derivative of the original data
deriv1_method3=signal.savgol_filter((np.diff(y)/np.diff(x)), 5,2)
1

There are 1 best solutions below

1
On BEST ANSWER

Under the hood signal.savgol_filter uses signal.savgol_coeffs if you look a the source code it says that "The coefficient assigned to y[deriv] scales the result to take into account the order of the derivative and the sample spacing". The results are hance scaled before performing the fitting and the convolve1d. So by default, it seems that the results are already scaled taking into account the order of derivatives.

I think that performing the derivative after computing Savitzky-Golay filter won't give you the same results because in this case, you are computing the derivative on the spectrum already filtered, while in the first case you are performing the derivative before performing the fitting and the scaling.