EKG Signal Processing An Algorithm To Detect and Align QRS Complx
EKG Signal Processing An Algorithm To Detect and Align QRS Complx
EKG Signal Processing An Algorithm To Detect and Align QRS Complx
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.
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.
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:
Main Program
Load ecgsignals
end
With the exception of the load ecgsignals step, the other steps are processed 4 times, one
per EKG signal.
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.
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
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.
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.
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.
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.
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)
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.
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.
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.
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.
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.
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
% ***********************************************
% 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.
% MAIN PROGRAM
% load EKG signals, remove offset and rename (y1,y2,y3,y4)
load ecgsignals;
% 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
for i=3:length(f1)
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
% 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.