MATLAB Answers

Detect and remove the artifacts in PPG signal via MATLAB

24 views (last 30 days)
Leo David
Leo David on 21 Nov 2020
Commented: Mathieu NOE on 23 Nov 2020
Hi,
There is the sample PPG data file, and there are 100 different PPG signals' data.
The sample frequency is about 30 Hz.
When I choose the 85th signal, the wavefrom is looked like this.
Obviously, the motion artifacts is between 200 sec to 500 sec.
I want to design a MATLAB code for detect whether the artfacts are and remove them.
Could anyone tell me how to do that?
I want to separate the whole waveform into different waveforms. Basicially, one waveform is for one period of PPG.
Then, to find the maximum and minimum points and calculate the difference. The parts with a great difference shall be the artifacts.
Could anyone tell how to do that via MATLAB code?
Thanks

  2 Comments

Mathieu NOE
Mathieu NOE on 21 Nov 2020
hello
it's not yet a firm answer , but this code was first to look at the data and see which criteria could be used to remove outliers
more work needed
infile='Examples.mat';
% read the sample waveform
data = load(infile);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FFT parameters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
NFFT = 256; %
NOVERLAP = round(0.75*NFFT);
w = hanning(NFFT); % Hanning window / Use the HANN function to get a Hanning window which has the first and last zero-weighted samples.
% spectrogram dB scale
spectrogram_dB_scale = 80; % dB range scale (means , the lowest displayed level is XX dB below the max level)
for ck = 1:10
x = data.ppg(ck).data;
samples = length(x);
Fs = 1;
time =(0:samples-1)/Fs;
% create a RMS enveloppe of the signal
N = 100; % buffer size for averaging
envelop = sqrt(myslidingavg(abs(x.^2), N));
% plot
figure(3*ck);
plot(time,x,'b',time,envelop,'r');grid
title('input waveform');
% measure zero crossing periods
threshold = mean(envelop);
[ind_crossing,x_crossing,y_crossing]= crossing_V6(x,time,threshold,'linear');
% keep only positive slope crossing points
ind = (1:2:length(ind_crossing));
period_time_interval = [diff(x_crossing(ind))];
figure(3*ck+1);
subplot(2,1,1),plot(time,x,'b',x_crossing(ind),y_crossing(ind),'+r');grid
subplot(2,1,2),plot(period_time_interval,'+r');grid
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% time / frequency analysis : spectrogram demo
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[sg,fsg,tsg] = specgram(x,NFFT,Fs,w,NOVERLAP);
% FFT normalisation and conversion amplitude from linear to dB (peak)
sg_dBpeak = 20*log10(abs(sg))+20*log10(2/length(fsg)); % NB : X=fft(x.*hanning(N))*4/N; % hanning only
% saturation of the dB range :
% saturation_dB = 60; % dB range scale (means , the lowest displayed level is XX dB below the max level)
min_disp_dB = round(max(max(sg_dBpeak))) - spectrogram_dB_scale;
sg_dBpeak(sg_dBpeak<min_disp_dB) = min_disp_dB;
% plots spectrogram
figure(3*ck+2);
imagesc(tsg,fsg,sg_dBpeak);colormap('jet');
axis('xy');colorbar('vert');grid
title(['Spectrogram / Fs = ' num2str(Fs) ' Hz / Delta f = ' num2str(fsg(2)-fsg(1)) ' Hz ']);
xlabel('Time (s)');ylabel('Frequency (Hz)');
end
Leo David
Leo David on 22 Nov 2020
My idea is the local maximal and local minimal for each period or pulse shall be lower or similar.
I know "findpeaks" function, but not know how to find which one is the maximal or mininal.
Could you tell me how to do that?
I am also not sure what the good PPG signal's performance is? like the difference between maximal and minimal.

Sign in to comment.

Answers (1)

Star Strider
Star Strider on 21 Nov 2020
One approach:
D1 = load('Leo David (2) Examples.mat');
ppg85 = D1.ppg(85).data;
idx = find(ppg85 < -2);
ppg85(1:max(idx)) = 0;
figure
plot(t, ppg85)
grid
producing:
Everything up to the last negative deflection in the interference didn’t look (to me) to be a valid PPG signal. So I just removed all of it up to that point.
I did a number of other approaches first, to see if I could retrieve the PPG signal from the interference (using the firls function to design a filter for that purpose that worked to an extent although not close to optimally). Those would have been interesting if they had worked, however they didn’t so will forever remain unpublished here. They worked on the rest of the signal, not the interference.

  4 Comments

Show 1 older comment
Leo David
Leo David on 22 Nov 2020
For ppg(75), the artifacts are in the left of the waveform; for ppg(76), they are in the middle.
How could I deal them? I am not sure how to fix your codes for those cases?
Regards
Star Strider
Star Strider on 22 Nov 2020
Using the complete record:
L = numel(ppg85);
t = linspace(0, 1, L)*Ts;
I’ve worked on this for a few hours again today.
There is no robust way to code this to eliminate the noise. I’ve not been able to deal with it either with a filtering approach or a threshold approach.
It would likely be best to simply not include the abberrant records in your analysis. I will post my filter design code if you want, however it simply does not produce the results that you want.
That’s simply the reality of signal processing of biomedical signals.
Mathieu NOE
Mathieu NOE on 23 Nov 2020
yes , I also tried to find a smart way to deal with these artifacts
at the end, I could not find a viable and robust solution to retrieve fraction of signals inside one of the 100 records
there is a cheap alternative, to discard the entire buffer if some metrics are inconsistent or non smooth enough

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by