Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

EKG Signal Processing An Algorithm To Detect and Align QRS Complx

Download as pdf or txt
Download as pdf or txt
You are on page 1of 33

FLORIDA INTERNATIONAL UNIVERSITY

Department of Electrical and Computer Engineering

EKG Signal Processing: An Algorithm to detect and align QRS


Complexes

Pablo Gomez, Ph.D.

Miami, November 10, 2002


OBJECTIVE

The purpose of this project is to process EKG signals using novel algorithms and
techniques to detect and align QRS complexes, compute their average RR interval, the
cardiac rhythm, and analyze the results.

PART I. EKG SIGNALS

Four EKG signals were provided in MATLAB format. The signals are vectors containing
7200 points sampled at 360 Hz. That is, the data files contain 20 seconds of EKG
information. Variable names in data file ecgsignals.mat are y1, y2, y3 and y4 for the ECG
signals and x for the base time.

The following 4 figures show the original ECG signals plotted with MATLAB script
found in Appendix A.

Figure 1. EKG signal 1.


Figure 2. EKG signal 2.

Figure 3. EKG signal 3.


Figure 4. EKG signal 4.

PART II. Initial QRS localization/Definition of an Average Beat.

Our goal now is to scan the EKG signals to find the QRS complexes. The template that
will be used to correlate and align the other heart beats, will be the one with the shortest
QRS duration.

We developed an efficient algorithm to detect and align the QRS complexes. The
following is the sequence of steps to detect and align the QRS complexes:

• Filter the input signal using a Butterworth Low-Pass filter


• Smooth the filtered signal using a Five Point Average that includes the point itself
and its four neighbors.
• The algorithm works in 2 modes: find a QRS onset or find a QRS offset.
• Start in find onset mode and locate 8 Consecutive Monotonically Increasing
points (8 points is equivalent to 20ms).
• When found, the prospect onset is located at the current point – 8. The value at the
onset point is saved. Switch to find offset mode.
• In find offset mode, the threshold, defined as 32% of the peak of the signal, has to
be reached within the next 15 points (41ms). If is not found, it was a false QRS
onset, switch back to find onset mode.
• If the threshold is reached, the search continues until the value of the signal falls
below the value found at the onset point. This point is saved as the QRS offset
and the mode is switched to find onset.
• Once all prospect QRS complexes are found and their onset/offsets stored in a
QRS matrix, the alignment in time using correlation begins.
• The QRS with the shortest duration is selected as a template. It is defined as
vector of 216 points (600ms) with the QRS onset located at point 76 (35% of
600ms).
• The template is correlated 21 times with the input signal. The reference point is
the QRS onset. The correlation point begins at the onset – 10 and ends at the onset
+ 10. The maximum correlation factor is compared against 0.5. If it is greater or
equal than 0.5 (50%) the QRS is admitted, otherwise is rejected. The value of
50% was chosen after analyzing the signals. The duration and amplitude of the
QRS complexes vary so much that a 50% will be necessary to detect all legitimate
QRS complexes.
• The Average Beat is obtained by adding the admitted QRS complexes and
dividing the result by the number of them.
• The R-R intervals are computed by calculating the difference between
consecutive QRS onsets. The RR average intervals in milliseconds are calculated,
as well as their standard deviations and the cardiac rhythm in pulses per minute.
The following diagram shows the MATLAB implementation of this technique.

Main Program

Load ecgsignals

findqrs (find QRS complexes)

getavgbeat (get average beat, correlate and align beats)

beatstat (calculates beats statistics)

printqrs (writes QRS matrix to text file for further analysis)

Plot average beat

end

With the exception of the load ecgsignals step, the other steps are processed 4 times, one
per EKG signal.

The corresponding MATLAB code can be found in Appendix B.


PART II Results and Discussion

Figures 5 through 8 show the average beats obtained for each EKG signal. It can be seen
that the noise has been removed. The resulting average beats resemble standard PQRST
signals.

Figure 5. Average Beat for EKG signal 1. Part II.


Figure 6. Average Beat for EKG signal 2. Part II.

Figure 7. Average Beat for EKG signal 3. Part II.


Figure 8. Average Beat for EKG signal 4. Part II.

A MATLAB script was written (plot_beats) to verify that the algorithms effectively
locate and align all possible QRS complexes in a signal. The code can be found at the end
of Appendix B. The following 3 figures show the 32 QRS complexes found for EKG
signal 2.
Figure 9. Beats 1 thru 12 in EKG signal 2.
Figure 10. Beats 13 thru 24 in EKG signal 2.
Figure 11. Beats 25 thru 32 in EKG signal 2.

The following table shows the statistical results of the signal analysis

Table 1. Statistical Results of Part II.

RR Average (ms) RR Std Deviation (ms) Cardiac Rhythm (ppm)


EKG Signal 1 732 42 82
EKG Signal 2 605 111 99
EKG Signal 3 1038 581 58
EKG Signal 4 1368 830 44
The following table presents the analysis of the EKG signals based on the statistical
results and observations.

Table 2. Analysis of Results of Part II.

EKG Analysis
Signal #
1 A little bit faster than the standard 72 ppm but basically this is a Normal
Sinus Rhythm. The small standard deviation indicates a constant rythm
2 Fast cardiac rhythm. This signal reflects a Sinus Tachycardia. The standard
deviation indicates that the QRS complexes have almost the same pattern
but the PP intervals vary.
3 The small rate of 58 ppm could be an indication of a Sinus Bradycardia but
the high standard deviation reflects a highly variable QRS pattern. Looking
at the input signal, some prolonged PR intervals could be due to a First
Degree AV Block
4 The cardiac rhythm is very slow (44 ppm) indicating a Sinus Bradycardia.
However, the high standard deviation shows an erratic pattern in the EKG
signal. Looking at the signal, the first 10 seconds show a frequency that is
almost doubled in the next 10 seconds. More information is required.
The following table shows the onsets, offsets and correlation coefficients found for EKG
signal 1.

Table 3. Sample locations for onsets/offsets in EKG signal 1.

Correlation Admitted
Onset Offset Coefficient rejected
134 157 0.953 1
428 453 0.977 1
697 720 0.96 1
964 985 0.983 1
1229 1250 0.962 1
1491 1516 0.855 1
1760 1788 0.952 1
2043 2071 0.961 1
2317 2340 0.823 1
2573 2597 0.926 1
2836 2856 1 1
3112 3134 0.962 1
3361 3383 0.909 1
3610 3631 0.965 1
3851 3883 0.946 1
4110 4135 0.878 1
4371 4392 0.921 1
4660 4683 0.968 1
4945 4968 0.803 1
5194 5218 0.753 1
5436 5456 0.741 1
5677 5699 0.659 1
5947 5977 0.896 1
6218 6241 0.95 1
6491 6515 0.729 1
6737 6765 0.728 1
6986 7009 0.873 1

A total of 27 QRS complexes were detected, aligned and averaged. This yields to a noise
reduction factor of 5.2 (the square root of 27). All of the QRS complexes detected were
admitted since their correlation factor is > 0.5
The following table shows the onsets, offsets and correlation coefficients found for EKG
signal 2.

Table 4. Sample locations for onsets/offsets in EKG signal 2.

Correlation admitted/ Comments


Onset Offset Coefficient rejected
171 190 0.546 1
Rejected because its correlation
400 416 0.17 0 coefficient is too low
626 642 0.649 1
868 884 0.867 1
1120 1136 0.887 1
1367 1383 0.942 1
1607 1622 1 1
1773 1790 0.95 1
1978 1994 0.954 1
2146 2162 0.921 1
2287 2303 0.728 1
2429 2445 0.853 1
2572 2591 0.954 1
2715 2732 0.953 1
2932 2948 0.938 1
3241 3259 0.818 1
3485 3503 0.819 1
3722 3739 0.866 1
3954 3970 0.979 1
4185 4201 0.877 1
4417 4436 0.518 1
4615 4630 0.942 1
4861 4877 0.947 1
5096 5112 0.861 1
Rejected because its correlation
5338 5353 0.497 0 coefficient is too low
5587 5604 0.617 1
5831 5847 0.642 1
6062 6078 0.828 1
6295 6310 0.905 1
6510 6526 0.985 1
6745 6760 0.96 1
6963 6979 0.861 1

Out of the 32 QRS complexes detected, 30 were admitted and 2 rejected. This yields to a
noise reduction of 5.47 (the square root of 30).
The following table shows the onsets, offsets and correlation coefficients found for EKG
signal 3.

Table 5. Sample locations for onsets/offsets in EKG signal 3.

Correlation admitted
Onset Offset Coefficient /rejected
185 206 0.902 1
848 862 0.866 1
1103 1121 0.943 1
1378 1395 0.965 1
1640 1653 1 1
1902 1923 0.978 1
2173 2192 0.965 1
2440 2460 0.969 1
3026 3044 0.933 1
3271 3284 0.956 1
3538 3555 0.914 1
3806 3825 0.914 1
4769 4792 0.9 1
5187 5205 0.948 1
5439 5460 0.974 1
5708 5724 0.973 1
6404 6423 0.941 1
6647 6663 0.956 1
6915 6928 0.938 1

All of the 19 QRS complexes detected were admitted, correlated and averaged. This
yields to a noise reduction factor of 4.36 (the square root of 19)
The following table shows the onsets, offsets and correlation coefficients found for EKG
signal 4.

Table 6. Sample locations for onsets/offsets in EKG signal 4.

Correlation admitted/
Onset Offset Coefficient rejected
162 178 0.963 1
1000 1019 0.886 1
1924 1940 0.758 1
2830 2849 0.824 1
3730 3748 0.891 1
4236 4254 0.933 1
4482 4500 0.979 1
4746 4764 0.933 1
5007 5022 1 1
5265 5281 0.983 1
5518 5535 0.981 1
5778 5800 0.974 1
6040 6061 0.964 1
6295 6311 0.96 1
7060 7078 0.972 1

All of the 15 QRS complexes detected were admitted, correlated and averaged. This
yields to a noise reduction factor of 3.87 (the square root of 15)

PART III. QRS Identification using an Average Template.

The same process explained in Part II is repeated here, but this time, the Average Beat
obtained in Part II is used as a template to correlate and align the remaining beats.
A MATLAB Program (see Appendix C) was written to carry out this task. The only
difference with the version for Part II, is that now function getavgbeat is called twice, the
first time to use the shortest QRS complex and obtain an average beat; the second time, to
use the average beat obtained the first time.

The script plots the average beats obtained in Part II in blue, and the new average beat in
red. As can be seen in the following 4 figures, the resulting Average Beats did not
change by using an average beat as a template.
Figure 12. Average Beat for EKG signal 1 using an average template.

Figure 13. Average Beat for EKG signal 2 using an average template.
Figure 14. Average Beat for EKG signal 3 using an average template.

Figure 15. Average Beat for EKG signal 4 using an average template.
The following table shows the statistical figures obtained in Part III.

Table 7. Statistical Results of Part III.

RR Average (ms) RR Std Deviation (ms) Cardiac Rhythm (ppm)


EKG Signal 1 732 42 82
EKG Signal 2 608 110 99
EKG Signal 3 1038 581 58
EKG Signal 4 1368 830 44

With the exception of EKG signal 2 the figures are the same as those obtained in Part II.
The reason for this small difference is that now, as shown in Table 9, one of the 2 QRS
complexes that were rejected in Part II for signal 2, has been admitted. This is due to the
fact that now all QRS complexes have a higher correlation coefficient as it was expected.

The advantage of using an average beat as a template is that now more true QRS
complexes are taken in consideration for correlation and average. This improves the
quality of the noise reduction process.

The following table shows the onsets, offsets and correlation coefficients for EKG signal
1, after performing the experiment in Part III.

Table 8. Location of onsets and offsets in EKG Signal 1.

Correlation
Onset Offset Coefficient admitted/rejected
133 156 0.976 1
428 453 0.964 1
697 720 0.981 1
964 985 0.942 1
1229 1250 0.929 1
1491 1516 0.968 1
1760 1788 0.946 1
2043 2071 0.933 1
2317 2340 0.95 1
2573 2597 0.98 1
2836 2856 0.945 1
3112 3134 0.989 1
3361 3383 0.986 1
3610 3631 0.906 1
3851 3883 0.916 1
4110 4135 0.977 1
4370 4391 0.982 1
4660 4683 0.978 1
4945 4968 0.948 1
5193 5217 0.916 1
5436 5456 0.893 1
5677 5699 0.836 1
5947 5977 0.947 1
6218 6241 0.971 1
6492 6516 0.892 1
6737 6765 0.891 1
6985 7008 0.972 1

The same number of QRS complexes were found, aligned and averaged. Some slight
variations on the onsets and offsets positions are found.

Table 9. Location of onsets and offsets in EKG Signal 2.

Correlation admitted Comments


Onset Offset Coefficient /rejected
171 190 0.777 1
400 416 0.448 0 Still rejected since it didn’t reach 0.5
626 642 0.842 1
868 884 0.97 1
1120 1136 0.966 1
1367 1383 0.981 1
1607 1622 0.942 1
1773 1790 0.922 1
1978 1994 0.959 1
2146 2162 0.929 1
2287 2303 0.869 1
2429 2445 0.856 1
2572 2591 0.897 1
2715 2732 0.918 1
2932 2948 0.973 1
3241 3259 0.952 1
3485 3503 0.957 1
3722 3739 0.972 1
3954 3970 0.976 1
4185 4201 0.959 1
4417 4436 0.75 1
4615 4630 0.953 1
4861 4877 0.975 1
5096 5112 0.96 1
It was admitted now since its correlation
5339 5354 0.74 1 coefficient > 0.5
5587 5604 0.815 1
5831 5847 0.847 1
6062 6078 0.954 1
6295 6310 0.961 1
6510 6526 0.909 1
6745 6760 0.93 1
6963 6979 0.951 1
One more QRS complex was found, aligned and averaged, due to its now higher
correlation coefficient factor. Some slight variations on the onsets and offsets positions
are found. The noise reduction factor increased.

Table 10. Location of onsets and offsets in EKG Signal 3.

Correlation admitted/
Onset Offset Coefficient rejected
185 206 0.962 1
848 862 0.953 1
1103 1121 0.98 1
1378 1395 0.986 1
1640 1653 0.968 1
1902 1923 0.957 1
2173 2192 0.981 1
2440 2460 0.984 1
3026 3044 0.986 1
3271 3284 0.986 1
3538 3555 0.975 1
3806 3825 0.977 1
4769 4792 0.965 1
5187 5205 0.977 1
5439 5460 0.96 1
5708 5724 0.972 1
6404 6423 0.976 1
6647 6663 0.985 1
6914 6927 0.981 1

The same number of QRS complexes were found, aligned and averaged. Some slight
variations on the onsets and offsets positions are found.

Table 11. Location of onsets and offsets in EKG Signal 4.

Correlation admitted/
Onset Offset Coefficient rejected
162 178 0.981 1
1000 1019 0.935 1
1924 1940 0.819 1
2830 2849 0.881 1
3730 3748 0.941 1
4236 4254 0.971 1
4482 4500 0.984 1
4746 4764 0.96 1
5007 5022 0.986 1
5265 5281 0.98 1
5518 5535 0.972 1
5778 5800 0.963 1
6040 6061 0.95 1
6295 6311 0.949 1
7059 7077 0.963 1

The same number of QRS complexes were found, aligned and averaged. Some slight
variations on the onsets and offsets positions are found.

COMPARISON VERSUS FREQUENCY DOMAIN

The main advantage of the time domain techniques used in this project versus similar
methods in the frequency domain, is that the processing time is smaller and that
frequency filtering not only removes noise but also components of the signal of interest at
the same frequency of the noise. An advantage of frequency domain methods is their
simplicity of implementation and accuracy, specifically when the frequency of the noise
is known in advance.

CONCLUSIONS

An effective time domain method to locate QRS complexes and process them to reduce
noise and obtain an average beat and useful statistical figures has been developed and
tested with excellent results.

A technique that uses Five Point Average in time and location of QRS complexes using a
Consecutive Monotonically Increasing Points Algorithm has been developed and proved
to be an efficient tool.

APPENDIX A

The following is the MATLAB code to plot the original signals.

% ***********************************************
% Script to load EKG signals from file
% and plot signals (sampling rate = 360 Hz)
load ecgsignals;

% plot signal 1:
figure;
subplot(2,1,1);plot(x(1:3600),y1(1:3600));
grid on;
xlabel('Time - Seconds');
ylabel('Amplitude - mV');
title('EKG signal n2000850');
subplot(2,1,2);plot(x(3601:7200),y1(3601:7200));
grid on;
xlabel('Time - Seconds');
ylabel('Amplitude - mV');

%plot signal 2:
figure;
subplot(2,1,1);plot(x(1:3600),y2(1:3600));
grid on;
xlabel('Time - Seconds');
ylabel('Amplitude - mV');
title('EKG signal n2092910');
subplot(2,1,2);plot(x(3601:7200),y2(3601:7200));
grid on;
xlabel('Time - Seconds');
ylabel('Amplitude - mV');

%plot signal 3:
figure;
subplot(2,1,1);plot(x(1:3600),y3(1:3600));
grid on;
xlabel('Time - Seconds');
ylabel('Amplitude - mV');
title('EKG signal n2321529');
subplot(2,1,2);plot(x(3601:7200),y3(3601:7200));
grid on;
xlabel('Time - Seconds');
ylabel('Amplitude - mV');

%plot signal 4:
figure;
subplot(2,1,1);plot(x(1:3600),y4(1:3600));
grid on;
xlabel('Time - Seconds');
ylabel('Amplitude - mV');
title('EKG signal n2322353');
subplot(2,1,2);plot(x(3601:7200),y4(3601:7200));
grid on;
xlabel('Time - Seconds');ylabel('Amplitude - mV');

APPENDIX B.

The following code is used to process the ECG signals

% MAIN PROGRAM
% load EKG signals, remove offset and rename (y1,y2,y3,y4)
load ecgsignals;

% process EKG signal 1:


[qrs,f1]=findqrs(y1);
[QRS, avgbeat,n]=getavgbeat(qrs,f1,1);
[RRavg1,RRdev1,RRppm1]=beatstat(QRS)
figure;plot(1/360:1/360:216/360,avgbeat);grid on;
title('Average Beat for EKG Signal 1');
xlabel('seconds');ylabel('millivolts');
printqrs(QRS,'ekg1.txt');

% process EKG signal 2:


[qrs,f1]=findqrs(y2);
[QRS, avgbeat,n]=getavgbeat(qrs,f1,1);
[RRavg2,RRdev2,RRppm2]=beatstat(QRS)
figure;plot(1/360:1/360:216/360,avgbeat);grid on;
title('Average Beat for EKG Signal 2');
xlabel('seconds');ylabel('millivolts');
printqrs(QRS,'ekg2.txt');
plot_beats(QRS,f1);

% process EKG signal 3:


[qrs,f1]=findqrs(y3);
[QRS, avgbeat,n]=getavgbeat(qrs,f1,1);
[RRavg3,RRdev3,RRppm3]=beatstat(QRS)
figure;plot(1/360:1/360:216/360,avgbeat);grid on;
title('Average Beat for EKG Signal 3');
xlabel('seconds');ylabel('millivolts');
printqrs(QRS,'ekg3.txt');

% process EKG signal 4:


[qrs,f1]=findqrs(y4);
[QRS, avgbeat,n]=getavgbeat(qrs,f1,1);
[RRavg4,RRdev4,RRppm4]=beatstat(QRS)
figure;plot(1/360:1/360:216/360,avgbeat);grid on;
title('Average Beat for EKG Signal 4');
xlabel('seconds');ylabel('millivolts');
printqrs(QRS,'ekg4.txt');

%*** end of main program ********

% FINDQRS:
%**********************************************************************
% Florida International University
% Department of Electrical and Computer Engineering
% ---------------------------------------------------------------------
% FUNCTION: findqrs
% this function finds all possible QRS complexes in an EKG signal
% provided as input.
% INPUTS = ekg (vector containing the EKG signal)
% OUTPUTS = QRS a 32x3 matrix containing the qrs complexes
% column 1 = onset, column 2 = offset, column 3 = duration
% f1, the filtered smoothed EKG signal
% ---------------------------------------------------------------------
% Author: Pablo Gomez, Ph.D. November 9, 2002
% ---------------------------------------------------------------------
function [QRS,f1]=findqrs(ekg)

% Lowpass Filter:
fs = 360; % sampling rate = 360 Hz
fc = 150; % cutoff frequency = 150 Hz
[B,A]=butter(9,fc/(fs/2)); % butterworth low-pass filter order 9
t1=filter(B,A,ekg); % filter input signal

% Smooth the filtered signal using a Five Point Average


f1=zeros(1,length(ekg));
for i=3:length(ekg)-2
f1(i)=(t1(i-2)+t1(i-2)+t1(i)+t1(i+1)+t1(i+2))/5;
end

k = 1; % number of QRS complexes found (index to QRS)


N = 8; % number of consecutive monotonically increasing points
QRS = zeros(32,3); % QRS matrix
counter = 0; % count number of monotonically increasing points
find_onset = 1; % Mode = 1 (find onset) Mode = 0 (find offset)
thr=0.32*max(f1); % threshold (32% of maximum amplitude)
thcnt=0; % counter of points found above threshold

for i=3:length(f1)

% find onset mode


if find_onset == 1
if (f1(i) > f1(i-1)) % monotonically increasing point?
counter=counter+1;
if counter == N % prospect QRS onset found
onset = i-N; % the onset is located N points before
find_onset = 0; % switch mode to find the offset
thcnt = 0;
counter = 0;
val = f1(i-N); % amplitude at onset point
QRS(k,1) = onset; % store onset in QRS matrix
end
else
% the amplitude went down, start all over again:
counter=0;
end

%searching for offset mode:


else
if f1(i) > thr % count number of points reaching
thcnt=thcnt+1; % the threshold, after a QRS onset
end % has been found

counter=counter+1;
if counter >= 15 & thcnt == 0 % 15 points = 41.7ms (15/360)
% false onset (after 15 points the threshold was not reached)
find_onset=1; % switch to find onset mode
counter=0;
else
% this is a QRS complex; look for the offset:
if f1(i) <= val % if amplitude falls below the
if thcnt >= 2 % the onset amplitude, we found the offset
offset = i;
QRS(k,2) = offset; % store offset in QRS matrix
duration = (offset-onset);
QRS(k,3) = duration; % store duration in QRS matrix
k = k+1; % next QRS complex
end
find_onset=1; % switch back to find onset mode
counter=0;
end
end
end
end
%*********** end of function *********************************************

% GETAVGBEAT:
%**********************************************************************
% Florida International University
% Department of Electrical and Computer Engineering
% ---------------------------------------------------------------------
% FUNCTION: getavgbeat
% this function finds all possible QRS complexes in an EKG signal
% provided as input.
% INPUTS = qrs matrix obtained previously by findqrs (prospect QRS)
% f1, the filtered smoothed EKG signal
% templ_type (1=use shortest QRS 2=provided as input parm
% templ, the template QRS when templ_type = 2
% OUTPUTS = QRS a 32x3 matrix containing the aligned qrs complexes
% (column 1 = onset, column 2 = offset,
% column 3 = correlation coefficient,
% column 4 = 1 admitted - 0 rejected)
% avgbeat, the average beat vector
% n, the number of beats aligned and averaged
% ---------------------------------------------------------------------
% Author: Pablo Gomez, November 10, 2002
% ---------------------------------------------------------------------
function [QRS, avgbeat,n]=getavgbeat(qrs,f1,templ_type,templ)

if templ_type == 1
% find shortest QRS:
shortest=999999;
for k=1:32
if qrs(k,2) > 0
if qrs(k,3) < shortest
shortest = qrs(k,3);
j=k;
end
end
end
% Build template (Length=216 points or 600ms;
% Onset at point 76 (35% of 600ms)
templ=f1(qrs(j,1)-75:qrs(j,1)+140);
end

% Get summation of squares of template points (used later by correlation coeff)


sum_templ=0;
for k=1:216
sum_templ=sum_templ+templ(k)^2;
end

% Correlate the template with all QRS complexes found:


QRS=zeros(32,4);
for k=1:32
% The criteria to admit a QRS complex is as follows:
% duration >= 36ms (13/360) and <= 94ms (34/360)
if qrs(k,3) >= 13 & qrs(k,3) <= 34
x=qrs(k,1); % onset of current QRS
max_corr=0; % Max correlation value
h=x; % alignment point starts at x
for m=x-10:x+10
corrv=0; % correlation value
for n=1:216
if (m+n-76) > 0 & (m+n-76) <= length(f1)
corrv = corrv + templ(n)*f1(m+n-76);
end
end
if corrv > max_corr
max_corr = corrv; % Max correlation value
h=m; % position of max correlation
end
end
% Summation of squares of ekg points in the template window:
sum_x=0;
for p=h-75:h+140
sum_x=sum_x+f1(p)^2;
end
corr_factor = max_corr/sqrt(sum_x*sum_templ);
% store the alignment and coefficient factor in QRS:
QRS(k,1)=h;
QRS(k,2)=h+qrs(k,3);
QRS(k,3)=max_corr/sqrt(sum_x*sum_templ);
% criteria to admit the QRS is correlation factor >= 50%
if corr_factor >= 0.5
QRS(k,4) = 1; % admitted
else
QRS(k,4) = 0; % rejected
end
end
end
% Compute Average Beat:
avgbeat=zeros(1,216); % 216 == 600ms (216/360)
n=0;
for k=1:32
if QRS(k,4) == 1
beat = f1(QRS(k,1)-75:QRS(k,1)+140);
avgbeat = avgbeat + beat;
n=n+1;
end
end
if n > 0
avgbeat=avgbeat/n;
end
%****** END OF FUNCTION ******

% BEATSTAT
% ---------------------------------------------------------------------
% FUNCTION: beatstat
% this function calculates the statistics of the EKG signal whose
% QRS matrix is passed as input parameter
% INPUTS = qrs (matrix obtained with getavgbeat)
% OUTPUTS = RRavg (average R-R in seconds)
% RRdev (standard deviation of R-R in seconds)
% RRppm (cardiac rhythm in pulses per minute)
% ---------------------------------------------------------------------
% Author: Pablo Gomez, November 10, 2002
% ---------------------------------------------------------------------
function [RRavg,RRdev,RRppm]=beatstat(qrs)

RR=zeros(1,length(qrs));
m=0;
for k=2:length(qrs)
if qrs(k,1) > 0 & qrs(k-1,1) > 0 & qrs(k,4) == 1
m=m+1;
RR(m)=qrs(k,1) - qrs(k-1,1); % RR interval
end
end
RRavg=mean(RR(1:m))/360; % sampling frequency = 360 Hz
RRdev=std(RR(1:m))/360;
RRppm=60/RRavg;
%**** end of function ********
%PRINTQRS:
function printqrs(qrs,filename)
fid=fopen(filename,'w');
for k=1:length(qrs)
if qrs(k,1) > 0
fprintf(fid,'%d, %d, %5.3f, %d \r\n',qrs(k,1),qrs(k,2),qrs(k,3),qrs(k,4));
end
end
fclose(fid);
% *** end of function *****

% PLOTBEATS:
% This function plots each QRS complex found on an EKG signal
function plot_beats(qrs, f1)
Y1=min(f1)-50;
Y2=max(f1)+50;
figure;
for k=1:12
if qrs(k,2) > 0
t=qrs(k,1)-75:qrs(k,1)+140;
subplot(4,3,k);plot(t,f1(t));grid on;
X1=qrs(k,1)-75;
X2=qrs(k,1)+140;
axis([X1 X2 Y1 Y2]);
end
end
figure;
for k=13:24
if qrs(k,2) > 0
t=qrs(k,1)-75:qrs(k,1)+140;
subplot(4,3,k-12);plot(t,f1(t));grid on;
X1=qrs(k,1)-75;
X2=qrs(k,1)+140;
axis([X1 X2 Y1 Y2]);
end
end
figure;
for k=25:32
if qrs(k,2) > 0
t=qrs(k,1)-75:qrs(k,1)+140;
subplot(4,2,k-24);plot(t,f1(t));grid on;
X1=qrs(k,1)-75;
X2=qrs(k,1)+140;
axis([X1 X2 Y1 Y2]);
end
end
APPENDIX C

The following is the code to process ECG signals using a template beat.

% load EKG signals, remove offset and rename (y1,y2,y3,y4)


load ecgsignals;

% process EKG signal 1:


[qrs,f1]=findqrs(y1);
[QRS, avgbeat,n]=getavgbeat(qrs,f1,1);
figure;plot(1/360:1/360:216/360,avgbeat);grid on;
title('Average Beat for EKG Signal 1');
xlabel('seconds');ylabel('millivolts');
[QRS, avgbeat,n]=getavgbeat(qrs,f1,2,avgbeat);
hold on;
plot(1/360:1/360:216/360,avgbeat,'r');
[RRavg1,RRdev1,RRppm1]=beatstat(QRS)
printqrs(QRS,'ekg1A.txt');
%plot_beats(QRS,f1);

% process EKG signal 2:


[qrs,f1]=findqrs(y2);
[QRS, avgbeat,n]=getavgbeat(qrs,f1,1);
figure;plot(1/360:1/360:216/360,avgbeat);grid on;
title('Average Beat for EKG Signal 2');
xlabel('seconds');ylabel('millivolts');
[QRS, avgbeat,n]=getavgbeat(qrs,f1,2,avgbeat);
hold on;
plot(1/360:1/360:216/360,avgbeat,'r');
[RRavg2,RRdev2,RRppm2]=beatstat(QRS)
printqrs(QRS,'ekg2A.txt');

% process EKG signal 3:


[qrs,f1]=findqrs(y3);
[QRS, avgbeat,n]=getavgbeat(qrs,f1,1);
figure;plot(1/360:1/360:216/360,avgbeat);grid on;
title('Average Beat for EKG Signal 3');
xlabel('seconds');ylabel('millivolts');
[QRS, avgbeat,n]=getavgbeat(qrs,f1,2,avgbeat);
[RRavg3,RRdev3,RRppm3]=beatstat(QRS)
hold on;
plot(1/360:1/360:216/360,avgbeat,'r');
printqrs(QRS,'ekg3A.txt');

% process EKG signal 4:


[qrs,f1]=findqrs(y4);
[QRS, avgbeat,n]=getavgbeat(qrs,f1,1);
figure;plot(1/360:1/360:216/360,avgbeat);grid on;
title('Average Beat for EKG Signal 4');
xlabel('seconds');ylabel('millivolts');
[QRS, avgbeat,n]=getavgbeat(qrs,f1,2,avgbeat);
[RRavg4,RRdev4,RRppm4]=beatstat(QRS)
hold on;
plot(1/360:1/360:216/360,avgbeat,'r');
printqrs(QRS,'ekg4A.txt');

% ***** End of Code ********

You might also like