I'm trying this on one of the signals (second subplot):
I am adding a link with the example signal used here exampleSignal
My signal is "ydata". To highpass the signal I tried:
vidInfo.frameRate = 29.9293;
highPassedSig = highpass(ydata,4,vidInfo.frameRate) % vidInfo.frameRate
It seems to me that there is some serious edge artifact. If I eliminate the first 50 and the last 50 samples, this is the central part of the signal:
To get rid of the edge artifact, I tried to make the signal longer at the beginning and the end. I tried two approaches: 1) zero padding, 2) doubling the first and last 50 samples of the signal. The zero padding didn't work. I found some code on mathworks for the second approach:
R=0.1; % 10% of signal
Nr=50;
N=size(ydata,1);
NR=min(round(N*R),Nr); % At most 50 points
for i=1:size(ydata,2)
ydata1(:,i)=2*ydata(1,i)-flipud(ydata(2:NR+1,i)); % maintain continuity in level and slope
ydata2(:,i)=2*ydata(end,i)-flipud(ydata(end-NR:end-1,i));
end
sigToHighPass=[ydata1;ydata;ydata2];
% Do filtering
highPassedSig = highpass(sigToHighPass,4,vidInfo.frameRate);
highPassedSig = highPassedSig(NR+1:end-NR,:)
It looks like the edge artifact is removed. At this point, I tried to apply the low-pass filter to the highpass filtered data.
N=size(highPassedSig,1);
NR=min(round(N*R),Nr); % At most 50 points
for i=1:size(highPassedSig,2)
highPassedSig1(:,i)=2*highPassedSig(1,i)-flipud(highPassedSig(2:NR+1,i)); % maintain continuity in level and slope
highPassedSig2(:,i)=2*highPassedSig(end,i)-flipud(highPassedSig(end-NR:end-1,i));
end
sigToLowPass=[highPassedSig1;highPassedSig;highPassedSig2];
% Do filtering
lowPassedSig = lowpass(sigToLowPass,0.7,vidInfo.frameRate);
lowPassedSig=lowPassedSig(NR+1:end-NR,:)
This is the result Once again, it looks like there is some serious edge artifact.
I also tried other approaches. For instance:
d = designfilt('lowpassfir', 'FilterOrder', 5, 'CutoffFrequency', 0.7, 'SampleRate', vidInfo.frameRate);
lowPassedSig = filter(d, ydata);
This is the result (subplot3):
Does anyone have any idea how can I deal with this?
Thank you,
Gianluca
the fundamental problem I see in your approach is that you are miss-interpreting your cut-off frequencies. If you want to remove frequencies below 0.7 Hz and above 4 Hz, you need :
Not the other way around !
This is easily done using the highpass
and lowpass
functions as you suggested. They are dealing with the padding automatically. If you want you can design your own digital filter BUT with the cut-off frequencies mentionned above :)
A matlab code that does what you want is :
ydata = load("signaldata.mat","-mat");
ydata = ydata.ydata;
f = 29.9293;
lp = 0.7;
hp = 4;
[y_hp,d_hp] = highpass(ydata,lp,f);
[y_lphp,d_lp] = lowpass(y_hp,hp,f);
%% plot result
x = (1:length(ydata))/f;
figure;
subplot(3,1,1);
plot(x,ydata);
legend("Original");
subplot(3,1,2);
plot(x,y_hp);
legend("Highpass");
subplot(3,1,3);
plot(x,y_lphp);
xlabel('Time [s]');
legend("Lowpass");
%% plot filters
figure;
[h,w] = freqz(d_hp);
subplot(2,2,1);
title('Highpass');
loglog(w/pi*f/2,abs(h));
subplot(2,2,3);
semilogx(w/pi*f/2,angle(h)/pi*180);
[h,w] = freqz(d_lp);
subplot(2,2,2);
title('Lowpass');
loglog(w/pi*f/2,abs(h));
subplot(2,2,4);
semilogx(w/pi*f/2,angle(h)/pi*180);
This gives the following plots : The input and output data The frequency responses (magnitude and phase) of the filters.
I hope this explanation will help you !