Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Savitzky-Golay filtering giving incorrect derivative in 1D

I have an x and y dataset, with x as the independent variable and y as the dependent variable.

y=2x


I add some noise to 'y' and apply the scipy Savitzky Golay filter. When I attempt to get the first derivative of y, I get the derivative as zero. I understand this is because of the filter takes only 'y' as the input. I would want to have a filter that considers both x and y, and also provide me with a derivative value.

Here I show my implementation with the plots indicating incorrect data.

import numpy as np
from scipy import signal
import matplotlib.pyplot as plt

# create some sample twoD data
x = np.linspace(-3,3,100)
y = 2*x
y = y + np.random.normal(0, 0.2, y.shape)

# filter it
Zn = signal.savgol_filter(y, window_length=29, polyorder=4, deriv=0)
Zf = signal.savgol_filter(y, window_length=29, polyorder=4, deriv=1)
# do some plotting
plt.plot(x,y, label = 'Input')
plt.plot(x,Zn, label= 'Savitzky-Golay filtered')
plt.plot(x,Zf, label= 'Savitzky-Golay filtered - 1st derivative')
plt.legend()
plt.show()

Result:enter image description here

The derivative result: dy/dx = 2.
I need the Savitzky-Golay filter to provide me this result. Please help me with a python implementation that considers two variables.

like image 342
Ankit Bansal Avatar asked Mar 03 '23 21:03

Ankit Bansal


2 Answers

To use deriv > 0 in savgol_filter, you must also give the spacing of the x coordinates. The fix is simple: add delta=x[1] - x[0] after deriv=1 in the call:

Zf = signal.savgol_filter(y, window_length=29, polyorder=4, deriv=1, delta=x[1] - x[0])
like image 74
Warren Weckesser Avatar answered Mar 09 '23 23:03

Warren Weckesser


In your case you have not dy/dx = 2, but dy/1.0 = 0.06 as you have x = np.linspace(-3,3,100).

You have not defined dx as delta and used the default value delta=1.0.

Therefore, using the delta, which is equal to dx fixes your problem.

dx = x[0] - x[1]
Zf = signal.savgol_filter(y, window_length=29, polyorder=4, deriv=1, delta=dx)
like image 22
Andrei Krivoshei Avatar answered Mar 09 '23 22:03

Andrei Krivoshei