# Sort a bank of ECG samples to 2 groups

조회 수: 5 (최근 30일)
Portalboi . 2023년 1월 6일
댓글: Star Strider . 2023년 1월 11일
Hey,
I've a bank of 2 types of ECG samples: link, some of them were measured while exercising and some while resting
all the samples are 5 seconds long, and were measured at 1k[Hz] frequency
I'm having a hard time develop an algorithem to sort that bank to 2 groups (exercising and resting)
any ideas?
##### 댓글 수: 3이전 댓글 2개 표시이전 댓글 2개 숨기기
Portalboi 2023년 1월 7일
Would you mind showing me how to start?

댓글을 달려면 로그인하십시오.

### 채택된 답변

Star Strider 2023년 1월 8일
편집: Star Strider 님. 2023년 1월 8일
This is the best I can do for these.
They required a significant amount of processing to remove the baseline variation and high-frequency noise. (The processing uses two filters, the first a notch filter to remove the 50 Hz line noise, and the second bandpass filter to eliminate baseline variation and high frequency noise. The detrend call removes any baseline variation left after filtering.) The ‘Before’ and ‘After’ plots are displayed for the first 20. The table at the end displays the rate and voltage for each filtered EKG. Some of them (for example #5 and #20) are so noisy that it is difficult to do anything with them. The noise can simply swamp the data, and it is difficult to do anything about that.
Of note, #2, #4, #14 and #18 display a strain pattern (significant S-T depression) that I find worrisome.
I’m not certain how best to classify them. There can be significant uncertainty since there can be individual variation that can make that difficult. It would be easier to classify the data for a single subject between rest and exercise than for all subjects.
Uz1 = 1×600 cell array
Fs = 1E+3;
Fn = Fs/2;
L = 5001;
t = linspace(0, L-1, L).'/Fs;
N = 20;
for k = 1:N%numel(Uz1)
EKG1(:,k) = LD.thisSignal;
end
Wp = [45 55]/Fn; % Passband Frequency (Normalised)
Ws = [48 52]/Fn; % Stopband Frequency (Normalised)
Rp = 1; % Passband Ripple
Rs = 60; % Passband Ripple (Attenuation)
[n,Wp] = ellipord(Wp,Ws,Rp,Rs); % Elliptic Order Calculation
[z,p,k] = ellip(n,Rp,Rs,Wp,'stop'); % Elliptic Filter Design: Zero-Pole-Gain
[sos1,g1] = zp2sos(z,p,k); % Second-Order Section For Stability
figure
freqz(sos1, 2^16, Fs) % Filter Bode Plot
Wp = [0.20 60]/Fn; % Passband Frequency (Normalised)
Ws = [0.10 65]/Fn; % Stopband Frequency (Normalised)
Rp = 1; % Passband Ripple
Rs = 60; % Passband Ripple (Attenuation)
[n,Wp] = ellipord(Wp,Ws,Rp,Rs); % Elliptic Order Calculation
[z,p,k] = ellip(n,Rp,Rs,Wp); % Elliptic Filter Design: Zero-Pole-Gain
[sos2,g2] = zp2sos(z,p,k); % Second-Order Section For Stability
figure
freqz(sos2, 2^16, Fs) % Filter Bode Plot
figure
for k = 1:N
subplot(N/5,5,k)
plot(t, EKG1(:,k))
grid
title(sprintf('%3d',k))
end
sgtitle('Original')
NFFT = 2^nextpow2(L);
Fv = linspace(0, 1, NFFT/2+1)*Fn
Fv = 1×4097
0 0.1221 0.2441 0.3662 0.4883 0.6104 0.7324 0.8545 0.9766 1.0986 1.2207 1.3428 1.4648 1.5869 1.7090 1.8311 1.9531 2.0752 2.1973 2.3193 2.4414 2.5635 2.6855 2.8076 2.9297 3.0518 3.1738 3.2959 3.4180 3.5400
Iv = 1:numel(Fv);
for k = 1:N
FTEKG1(:,k) = fft(EKG1(:,k)-mean(EKG1(:,k)),NFFT)/L;
end
% NrSp = size(EKG1,2);
figure
for k = 1:N
subplot(N/5,5,k)
plot(Fv, abs(FTEKG1(Iv,k))*2)
grid
xlim([00 60])
title(sprintf('EKG1 %3d',k))
end
for k = 1:size(EKG1,2)
EKG1(:,k) = filtfilt(sos1,g1,EKG1(:,k));
EKG1(:,k) = filtfilt(sos2,g2,EKG1(:,k));
EKG1(:,k) = detrend(EKG1(:,k),7);
end
figure
for k = 1:N
subplot(N/5,5,k)
plot(t, EKG1(:,k))
grid
[pks,locs] = findpeaks(EKG1(:,k), 'MinPeakProminence',(max(EKG1(:,k)))*0.75);
Ratev = 60./(diff(t(locs)));
Rate(k,:) = mean(Ratev);
RateSD(k,:) = std(Ratev);
V(k,:) = mean(pks);
VSD(k,:) = std(pks);
title(sprintf('EKG1 %3d',k))
end
sgtitle('Filtered')
EKG1_Nr = (1:N).';
RateVoltage = table(EKG1_Nr,Rate,RateSD,V,VSD)
RateVoltage = 20×5 table
EKG1_Nr Rate RateSD V VSD _______ ______ _______ ______ ______ 1 67.27 1.5015 241.39 23.72 2 58.626 2.1835 217.96 23.116 3 133.7 1.0487 139.12 25.277 4 69.981 4.2635 243.16 32.659 5 108.31 49.523 9.7718 3.6276 6 125.28 1.6384 178.06 9.3044 7 167.41 76.17 146.59 21.607 8 112.97 3.2368 115.67 3.8871 9 101.82 2.5095 58.848 6.8476 10 100.08 0.73725 67.919 19.926 11 160 43.114 89.831 30.63 12 95.054 37.807 146.45 50.934 13 94.06 7.5359 99.355 6.2704 14 63.155 3.6628 221.59 23.772 15 89.628 6.7647 92.713 1.8705 16 92.555 8.6227 90.693 5.4217
EDIT — (8 Jan 2023 at 11:54)
Added ‘RateSD’ and ‘VSD’ to calculations and to the table. Code otherwise unchanged.
.
##### 댓글 수: 2이전 댓글 1개 표시이전 댓글 1개 숨기기
Star Strider 2023년 1월 11일
As always, my pleasure!
The standard deviation (specifically ‘coefficient of variation’, defined as the standard deviation divided by the mean) can be helpful is assessing the quality of the data. The larger it is, the less reliable the data are.

댓글을 달려면 로그인하십시오.

### 추가 답변 (1개)

Vilém Frynta 2023년 1월 6일
편집: Vilém Frynta 님. 2023년 1월 6일
Hello,
as Star Strider already mentioned, you can filter data based on the R-amplitude and or heart rate (time between R–R).
I have tried to plot your data and it seems there is quite a big difference in amplitudes, so it appears that it could be a reliable filter.
Also, I am not very confident whether this is valid option, but I tried to perform FFT on your data, and it looks like there might be a difference between resting ECG and excersing ECG. But it is possible that I have chosen some data that are "perfect" and this might not be the case for the rest of your data.
See images below;
== example 1 and it's FFT ==
== example 2 and it's FFT ==

댓글을 달려면 로그인하십시오.

### 카테고리

Help CenterFile Exchange에서 Single-Rate Filters에 대해 자세히 알아보기

### Community Treasure Hunt

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

Start Hunting!

Translated by