The Savitzky-Golay filter is a widely-used technique in signal processing aimed at reducing noise and enhancing the smoothness of signal trends. This filter achieves this by computing a polynomial fit for each window, with parameters such as polynomial degree and window size influencing the smoothing process.
The SciPy library offers the savgol_filter() function, which facilitates the implemention of the Savitzky-Golay filter. In this tutorial, we'll provide an overview of utilizing the savgol_filter() function to effectively smooth signal data in Python..
The tutorial covers:
- Preparing signal data
- Smoothing with the Savitzky-Golay filter
- Source code listing
We'll start by loading the required libraries.
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
x = np.arange(-2, 2, 0.02)
y = np.array(x**2 + 2*np.sin(x*np.pi))
y = y + np.array(np.random.random(len(x)) * 2.3)
plt.figure(figsize=(12, 9))
plt.plot(x, y, label="y_signal")
plt.legend()
plt.grid(True)
plt.show()
y_smooth = signal.savgol_filter(y, window_length=11, polyorder=3, mode="nearest")
The mode parameter in the savgol_filter() function is optional and determines the type of extension to use for the padded signal to which the filter is applied. The mode can be defined as one of the following types: 'mirror', 'nearest', 'constant', and 'wrap'. You can choose the appropriate mode based on the characteristics of your data and the desired behavior at the signal boundaries. More details about each mode and other optional parameters of the function can be found in the SciPy reference page.
After applying the Savitzky-Golay filter to the data, we visualize the smoothed data in a graph to observe the effect of the smoothing operation.
plt.figure(figsize=(12, 9))
plt.plot(x, y, label="y_signal")
plt.plot(x, y_smooth, linewidth=3, label="y_smoothed")
plt.legend()
plt.grid(True)
plt.show()
Now we adjust the window size and polynomial order parameters to effectively smooth the trend of a signal. In this example, we'll experiment with multiple window sizes to observe their smoothing effects on a given dataset.
ig, ax = plt.subplots(4, figsize=(8, 14))
i = 0
# define window sizes 5, 11, 21, 31
for w_size in [5, 11, 21, 31]:
y_fit = signal.savgol_filter(y, w_size, 3, mode="nearest")
ax[i].plot(x, y, label="y_signal", color="green")
ax[i].plot(x, y_fit, label="y_smoothed", color="red")
ax[i].set_title("Window size: " + str(w_size))
ax[i].legend()
ax[i].grid(True)
i+=1
plt.tight_layout()
plt.show()
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
x = np.arange(-2, 2, 0.02)
y = np.array(x**2+2*np.sin(x*np.pi))
y = y + np.array(np.random.random(len(x))*2.3)
plt.figure(figsize=(12, 9))
plt.plot(x, y, label="y_signal")
plt.legend()
plt.grid(True)
plt.show()
y_smooth = signal.savgol_filter(y, window_length=11, polyorder=3, mode="nearest")
plt.figure(figsize=(12, 9))
plt.plot(x, y, label="y_signal")
plt.plot(x, y_smooth, linewidth=3, label="y_smoothed")
plt.legend()
plt.grid(True)
plt.show()
ig, ax = plt.subplots(4, figsize=(8, 14))
i = 0
# define window sizes 5, 11, 21, 31
for w_size in [5, 11, 21, 31]:
y_fit = signal.savgol_filter(y, w_size, 3, mode="nearest")
ax[i].plot(x, y, label="y_signal", color="green")
ax[i].plot(x, y_fit, label="y_smoothed", color="red")
ax[i].set_title("Window size: " + str(w_size))
ax[i].legend()
ax[i].grid(True)
i+=1
plt.tight_layout()
plt.show()
A very helpful post and an elegant bit of code. Thanks.
ReplyDeletethank you!!
ReplyDeletegreat
ReplyDelete