1
$\begingroup$

The following two figures show raw data and filtered data recorded in a measurement. I have used SciPy's Savizky-Golay filter with window_length = 6 and polyorder of 3 to obtain the second plot. One can see, that the filtration has distorted the endpoints. Also bumps seen in the raw data is not completely gone either, one or two being clearly visible.

I have the following questions:

  1. How do I supress the boundary effects?

  2. I would like to know is it recommended to apply the Sav-Gol filter to data taken in a measurement or is it meant for some other purposes.

  3. Are there any other filtration methods that you know of that can be better in cases such as this?

  4. Can journal publishers object to data filtered in this way as it might distort original data points that are nighbouring to noisy data points?

I would appreciate any help on this.

Plot of raw data: Plot of raw data

Result of Sav-Gol filter: Result of Sav-Gol filter

$\endgroup$

1 Answer 1

1
$\begingroup$

A robust approach for post process filtering without edge effects (or minimum edge effects) is to combine forward-backward filtering with mirror padding. The function filtfilt available in MATLAB, Octave and Python implements a zero phase "forward backward" filter, resulting in no time offsets while using the prescribed filter twice (once in the forward direction and once in the reverse direction and thus cancelling the filters own delay).

However filtfilt used on its own will have edge effects due to Gibbs-like ringing near the edges due to the abupt change in the samples there. This is reduced by appending additional samples to the front and end prior to doing the filtering. Mirror padding reflects the existing data without duplicating the edge values, and is simple and robust to use, but linear extrapolation can also be used as an alternative solution (better when signals tend to be linear at the edges such as the OP's case here).

Either way, below shows an example filtering implementation in Python which should provide an excellent result for this application (choose the cutoff frequency based on smoothing desired while not losing the true curvature of the waveform):

nyq = 0.5 * fs # fs is sampling rate in Hz normalized_cutoff = cutoff / nyq # choose a cutoff freq in Hz # filter coefficients, Butterworth in honor of my friend Hilmar b, a = butter(order, norm_cutoff, btype='low', analog=False # mirroring at edges (or do linear extrapolation: try both and compare!) pad_length = 5 * max(len(a), len(b)) data_padded = np.pad(data, pad_width=pad_length, mode='reflect') filtered = filtfilt(b, a, data_padded) # remove padding filtered = filtered[pad_length: -pad_length] 

As mentioned, a linear extension would provide even better results for padding the signal such that both the value and first derivative are continuous. Below shows the code that could be used in place of the one np.pad() line above:

left_slope = data[1] - data[0] right_slope = data[-1] - data[-2] left_pad = data[0] - left_slope * np.arange(pad_width, 0, -1) right_pad = data[-1] + right_slope * np.arange(1, pad_width + 1) data_padded = np.concatenate([left_pad, data, right_pad]) 

NOTE: The Savitksy-Golay filter provided by Python (scipy.signal.savgol_filter) provides mirror padding as a direct option in its impelmentation (see doc here for parameter mode: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.savgol_filter.html ) and for the same reasons given above can be instead combined with the custom derivative-matched padding for explicit control over the edge behavior:

window_length = 2 * pad_width # enter order desired for filter smoothed = scipy.signal.savgol_filter(data_padded, window_length, order) smoothed = smoothed[pad_width:-pad_width] 
$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.