Sunteți pe pagina 1din 14

Owen Humphreys

10382535

load ecgpvcs.mat
y=length(ecg1);
d=[1:y]/200;
ecg1=ecg1/1000;

%determining number of samples in data%


%to convert into time domain%
%convert to volts

%%%%%%%%%%%%%plot
figure(1)
plot(d,ecg1)
xlabel 'seconds'
ylabel 'Volts'
title 'Time domain: original signal'
N = 2048;
X = abs(fft(ecg1,N));
X = fftshift(X);
F = [-N/2:N/2-1]/N*200;
figure(2)
plot(F,X)
xlabel 'frequency'
title 'Frequency domain: original signal'

Figure 1 unfiltered ecg signal in time domain

Owen Humphreys
10382535

Figure 2 closer view of unfiltered ecg signal in time domain

Figure 3 unfiltered ecg signal in frequency domain

Owen Humphreys
10382535

%%%%%%%%%%%%%%%%

filter

% 50 Hz notch filter
wo = 50/(500/2); bw = wo/35;
[num,den] = iirnotch(wo,bw);
ecg1=filter(num,den,ecg1);
% 60 Hz notch filter
wo = 60/(500/2); bw = wo/35;
[num,den] = iirnotch(wo,bw);
ecg1=filter(num,den,ecg1);
% high pass filter
Fs=200;
Fn=Fs/2;
Ws=2/Fn;
Wp=0.1/Fn;
Rp=0.1;
Rs=40;
[n,Wn] = buttord(Wp,Ws,Rp,Rs);
[num,den]=butter(n,Wn,'high');
ecg1=filter(num,den,ecg1);

Figure 4 filtered ecg signal in time domain

Owen Humphreys
10382535

Figure 5 closer view of filtered ecg signal in time domain

Figure 6 filtered ecg signal in frequency domain

Figure 3 unfiltered ecg signal in frequency domain shows a very large peak at
around 0 Hz. There is no peak at 50 or 60 Hz so the notch filters have no effect.
After the low pass filter the large peak at around 0 Hz is attenuated. Figure 5 closer
view of filtered ecg signal in time domainshows a closer view of the signal in the
time domain; the low frequency noise due to body movement has been removed
and the ECG signal has become straighter. The removal of the DC or very low

Owen Humphreys
10382535
frequency signal results in the baseline at 0 V as expected, whereas it was at 2 V
before filtering.

%%%%%%%%%%%%%%%% Peak Detection


ecg1 = sgolayfilt(ecg1,7,21);

%smooth signal

%find R peaks
[~,R]=findpeaks(ecg1,'MinPeakHeight',0.4);
%separate into R peaks into R Normal and R PVC
R_normal = R(ecg1(R)>0.4 & ecg1(R)<0.65);
R_pvc= R(ecg1(R)>0.65);
%find S Peaks
ecg1_inverted=-ecg1;
%invert ecg to find S peak
[~,S]=findpeaks(ecg1_inverted,'MinPeakHeight',0.3);
[Rmag, Smag] = deal(ecg1(R), ecg1(S));

%%%%%%%%%plot
figure
hold on
plot(ecg1)
xlabel 'seconds'
ylabel 'Volts'
title 'Time domain: peak detection'
plot(R_normal,ecg1(R_normal),'rv','MarkerFaceColor','r');
plot(R_pvc,ecg1(R_pvc),'rv','MarkerFaceColor','y');
plot(S,ecg1(S),'rv','MarkerFaceColor','g');

Owen Humphreys
10382535

Figure 7 ECG with Normal R, PVC R, and S peaks isolated

Figure 8 Closer view of ECG with Normal R, PVC R, and S peaks isolated

This method can detect the normal R peak (red), PVC R peak (orange), normal S
peak (green), and PVC S peak (also green, they have not been separated). The
distance between these peaks could then be calculated, this would give more
features to classify the PVC beats than the Pan Tompkin. Although the signal needs

Owen Humphreys
10382535
to be much smoother because there are many false detections. Therefore the Pan
Tompkin code is used instead.

%%%%%%%%%%Pan Tompkin
[qrs_amp_raw,qrs_i_raw,delay]=pan_tompkin(ecg1,200,1);

Figure 9 Output of Pan Tompkin

Owen Humphreys
10382535

Figure 10 Closer view of Output of Pan Tompkin

The Pan Tompkin first applies a low pass filter to remove high frequency noise. It
then applies a high pass filter to remove low frequencies caused by body
movement. It squares the magnitude to reduce low amplitude signals and amplify
the large amplitude signals. This creates just two peaks per beat which makes it
easier for peak detection. The signal is then averaged over 30 samples to create a
single peak for peak detection.

Figure 11 Output of Pan Tompkin

Owen Humphreys
10382535

Figure 12 Closer view of output of Pan Tompkin

The red line is the moving average of the amplitude of the peaks. A PVC R peak is
identified if it is above this red line. The Pan Tompkin also calculated the distance
between the R peaks, this is used as the second feature for classification.
The Pan Tompkin outputs the amplitude of the R wave, and the sample number it
occurred at.
Comparing the Pan Tompkin output to the original ECG signal it is clear that the Pan
Tompkin output is shifted. The output points do not need to fit absolutely on the
ECG, they just need to be correct relative to each other. It is only the relative
heights and distances between the points that is needed to identify PVC beats.

Owen Humphreys
10382535

Figure 13 Comparing original ECG signal to output of Pan Tompkin (green circles)

%%%%%%%%%%%%%%%%%%% feature selection


%change from 1 row 401 columns to 401 rows 1 column
feature1=rot90(qrs_amp_raw);
feature2=[zeros(401,1)];
%initialise vector
feature2(1)=26;
%set first value, this won't work in loop
%find relative distance between peaks by subtracting absolute
values

Owen Humphreys
10382535

k=2;
while k<402
feature2(k)=qrs_i_raw(k)-qrs_i_raw(k-1);
k=k+1;
end
The class is notated by 1 = PVC, -1 = Normal. The class is set by choosing every R
peak that is above the value of 0.55, then manually checking and changing if any of
the values are incorrect.

%%%%%% set class


class=[zeros(401,1)];
k=1;
while k<402
if feature1(k)>0.55
class(k)=1;
else
class(k)=-1;
end
k=k+1;
end
%store classes and features
data=[class feature1 feature2];
%split into train and test data
train_data=data(1:120,:);
test_data=data(120:401,:);
%%split classes
c1=find(train_data(:,1)==1);
c2=find(train_data(:,1)==-1);
%%find best features
correlation=abs(corrcoef(train_data))
scatter(train_data(c1,3),train_data(c1,2), 'b')
hold on
scatter(train_data(c2,3),train_data(c2,2), 'r')
xlabel 'Samples between R peaks'
ylabel 'Magintude of R peaks'
title 'Magnitude Vs Distance between R peaks'
Class

Feature 1

Feature 2

Owen Humphreys
10382535
1.0000

0.9530

0.1644

0.9530

1.0000

0.0731

0.1644

0.0731

1.0000

Figure 14 Table of correlation values

The correlation function shows a very high correlation between the class and the
height of the R peak.
This can also be seen with a scatter plot of the data.
There is a very clear separation between the two groups of data on the magnitude y
axis. A hyperplane could be drawn between the two sets of data at about 110
samples on the x axis (the distance between the R peaks), but the data is much
closer together and the correlation is not as good.

Good hyperplane

Figure 15 scatter plot showing correlation

%%%%%%%%%%% Train_data Accuracy


Predicted_Train_lebels = classify (train_data(:,2:3) ,
train_data(:,2:3) ,train_data(:,1));
accuracy_train=train_data(:,1)-Predicted_Train_lebels;
k=1;
count=0;
while k<121
if accuracy_train(k,:)==0;
count=count+1;
end
k=k+1;

Owen Humphreys
10382535

end
accuracy_Predicted_Train_lebels=count/120

%%%%%%%%%%% Test_data Accuracy Feature1


clc
Predicted_Test_lebels = classify (test_data(:,2) ,
train_data(:,2) ,train_data(:,1) );
accuracy_test=test_data(:,1)-Predicted_Test_lebels
k=1;
count=0;
while k<283
if accuracy_test(k,:)==0;
count=count+1;
end
k=k+1;
end
accuracy_Predicted_Test_lebels=count/282

%%%%%%%%%%% Test_data Accuracy Feature2


clc
Predicted_Test_lebels = classify (test_data(:,3) ,
train_data(:,3) ,train_data(:,1) );
accuracy_test=test_data(:,1)-Predicted_Test_lebels
k=1;
count=0;
while k<283
if accuracy_test(k,:)==0;
count=count+1;

Owen Humphreys
10382535

end
k=k+1;
end
accuracy_Predicted_Test_lebels=count/282

%%%%%%%%%%% Test_data Accuracy Feature1 & Feature2


clc
Predicted_Test_lebels = classify (test_data(:,[2 3]) ,
train_data(:,[2 3]) ,train_data(:,1) );
accuracy_test=test_data(:,1)-Predicted_Test_lebels
k=1;
count=0;
while k<283
if accuracy_test(k,:)==0;
count=count+1;
end
k=k+1;
end
accuracy_Predicted_Test_lebels=count/282

Feature
Train Data
Test Data: Feature1 R Magnitude
Test Data: Feature2 Distance between
R peaks
Test Data: Feature1 & Feature2

Accuracy
100 %
97.16 %
68.79 %
96.45 %

Conclusion: The most accurate feature to classify the test data is the R
peak magnitude alone.

S-ar putea să vă placă și