0
votes

I'm recording a signal (skin conductance) over time, i.e. I have a time series. Unfortunately, the signal is affected by movement. In a user guide I have now read the following:

A low pass filter should be applied to the data to remove high frequency noise which can be attributed to movement artifact and other noise components. A cutoff frequency of as low as 1 - 5 Hz can be used without affecting the data of interest due to the slowly varying nature of GSR responses.

How can I apply such a low pass filter with a cutoff frequency to my time series in Matlab or Python?

2
Research and understand what a low pass filter is; imagine how one might be built/coded; see if there are any algorithms floating around; see if someone else already built one that is compatible with the object that contains your data; apply the filter to your data.wwii

2 Answers

1
votes

In Matlab, the easiest way to do this is probably to make use of the butter command (to find the coefficients of your digital filter), followed by the filter command: https://www.mathworks.com/help/signal/ref/butter.html

butter(n, Wn) will take as parameters the order of the filter you want to design (the higher the order, the more ideal in behavior the filter), and the normalized frequency, Wn. Typically, in order to design the filter correctly, you need to know at what frequency (Hz) your raw data was sampled.

Since you only need to remove baseline low frequency noise, use a high pass filter.

Example:

rawdata=rand(1000,1); %randomly generated data

fs=1000; %frequency at which your data was sampled, assuming 1000 Hz here

fc=5; %cut-off frequency (you mentioned 1-5 Hz in your question so I used 5)

Wn= fc/fs; % Normalized frequency

filt_order=8; % arbitrarily chose an 8th order filter

[b,a]=butter(filt_order,Wn, 'high'); 
% butter creates the coefficients of your digital filter
% the optional parameter 'high' specifies a high-pass filter

filtered_data=filter(b,a,rawdata);
1
votes

Designing a filter can be quite a complex process, no one can give you an answer right of the bat. Filter design is a skill gained from experience, but before gaining that experience, it is important to obtain a solid understanding of the basics of filters. You should get at least familiarized with FIR and IIR filters (pros and cons), what low/high/band-pass filters are and the basics of sampling.

In your case I am assuming that you already have the time series stored somewhere in memory, so you don't need to filter the data while measuring. In this case I would choose a FIR filter and would filter the data in the forward and backward direction with Matlab's function filtfilt, so your filtered signal will have no phase distortion. This type of filtering is only possible in post-processing, when the data is already collected, since this is non-causal filtering, where you know the value of the data points before and after, a certain data point. Whereas you would not know the future values if you were filtering while recording.

The filter order and the cutoff frequency are usually selected with an iterative process. One thing to keep in mind is that by increasing the filter order you are improving filter's performance (steeper roll-off slope), that comes with higher computational requirements.

Below is a short example with a signal that consists of two sine waves with frequencies 3 Hz and 25 Hz. The goal of filtering is to design a low-pass filter that would remove the 25 Hz frequency component. I want to show the performance of two different filters, one with the order 45 and another with order 70.

% sampling frequency [Hz]
Fs = 1000;
% sampling period [s]
Ts = 1/Fs;

% time vector [s]
t = 0:Ts:3;

% Signal A frequency [Hz] and amplitude
amplitude_A = 5;
f_A = 3;
sig_A = amplitude_A.*sin(2*pi*f_A.*t);

% Signal A frequency [Hz] and amplitude
amplitude_B = 2;
f_B = 25;
sig_B = amplitude_B.*sin(2*pi*f_B.*t);

% sum of the two signals
X = sig_A + sig_B;
plot(t,X,'LineWidth',2);
hold on;
grid on;

% Low pass filter at ~15Hz
% normalized frequency wn
wn = 15/Fs;
b_1 = fir1(45,wn);
b_2 = fir1(70,wn);

% filtered signal
a = 1; % fir filter does not have poles (transfer function denominator = 1)
Y_1 = filtfilt(b_1,a,X);
plot(t,Y_1,'-r','LineWidth',2);
Y_2 = filtfilt(b_2,a,X);
plot(t,Y_2,'-k','LineWidth',2);
xlabel('Time (s)');
ylabel('Amplitude (V)');
legend('original signal','filtered order 45',...
    'filtered order 70');

Here is the output:

enter image description here

On the graph you can see that the filter with a lower order did not filter the higher frequency component completely, but both filters attenuated the amplitude of the signal. The output could have been improved by tweaking the cutoff frequency and the filter order. This is also an easy filtering example, if the two components were closer in frequency, it would have been much more challenging to get a good result.

For your case I am assuming that the skin conductance (GSR) has a much lower frequency (below 1 Hz) than the artifacts induced by movement, so movement is a higher frequency component, which you wanna get rid of. I think you should carefully observe the raw signal plot and try to identify what changes are caused by movement, then filter the signal and check if that movement component was reduced, keep changing the filter parameters until you are happy with the result. Also (if needed) you should look into obtaining the frequency spectrum of the signal (perform FFT), which can help you select the cutoff frequency. If the recommended cutoff is somewhere from 1-5 Hz, I would start of with that and see if a frequency in that range does it.

It's pretty much impossible to explain filtering in one post, but just to get you started, it's good to know some of the basics. Remember that in filter design there is usually no perfect solution, since every filter distorts the original data in some way or another.