Sunteți pe pagina 1din 13

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 frequency signal results in the
baseline at 0 V as expected, whereas it was at 2 V before filtering.

Owen Humphreys
10382535

%%%%%%%%%%%%%%%% 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 to be much smoother because there are many false detections. Therefore the Pan Tompkin
code is used instead.

Owen Humphreys
10382535

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

Figure 9 Output of Pan Tompkin

Figure 10 Closer view of Output of Pan Tompkin

Owen Humphreys
10382535
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

Figure 12 Closer view of output of Pan Tompkin

Owen Humphreys
10382535
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.

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

Owen Humphreys
10382535

%%%%%%%%%%%%%%%%%%% 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
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);

Owen Humphreys
10382535

%%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

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

Owen Humphreys
10382535

%%%%%%%%%%% 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;
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

Owen Humphreys
10382535

%%%%%%%%%%% 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;
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