electrocardiogram parametrization of waves
TRANSCRIPT
Electrocardiogram – parametrization of waves
Introduction
Electrophysiological process in the health heart generates ECG signals, that reflects the summation of
action potentials in individual hearth structures dependent on a heart cycle. The cycle starts by the
atriums depolarization (P-wave), ventricles depolarization (QRS complex) and repolarization ventricles
(T-wave). Although signal waveform variability is relatively high between individual persons, the time-
dependent sequence of the waves, their polarity and amplitudes are strictly defined, that reflects the
heart condition. A valid interpretation of ECG can be carried out only by the experienced cardiologist,
however, the modern ECG system allows automatic parametrization and classification of the
waveforms to time-saving. The parametrization is fixed to the strongest R-peaks detection; subsequent
measuring of weak waves is performed between two cycles called R-R interval. Professional ECG
systems contain algorithm, which combines signals from all 12 leads for robust parametrisation also
pathological ECG. The main goal of this exercise is the basic measuring of normal ECG in the II. lead.
Aims:
1. Record ECG (I. and II. leads) 30 seconds in relax 2. Detect all R-peaks 3. Detect P, Q, S, T maximum in each R-R interval 4. Use triangle-detector to find the onset of P, Q, T waves and end of P, Q, S(J), T 5. Implement the function with outputs of the onsets, maxima, ends of waves 6. Automatically parametrise ECG signal:
intervals P, PQ (PR), Q, QRS, QT
amplitudes of maxima P, R, T, and ST segment 7. Compute electrical heart-axes using (I, aVf) leads for P, R, T waves 8. Show (I, II, III, aVR, aVL, aVF) leads in normalised grid and results of automatic parametrisation 9. Compare automatic and manual measurement of ECG
Recording of ECG: I. lead:
- white (-): right hand
- red (+): left hand - black (ref): right leg
II. lead:
- white (-): right hand
- red (+): left leg - black (ref): right leg
Thirty seconds ECG is recorded in sit, without talking, in a relaxed position, with normal breathing. Minimize the induction loop to minimize main hum noise. Note: You can use the first 30 seconds of signals from the previous exercise. Data structure: fs=500 Hz
1. column … lead I [mV] 2. column … lead II [mV]
Useful functions:
butter, freqz, zplane, impulse, function, filtfilt, compass, gca, pbaspect, set, get
Help:
1) Detection of R-peaks: R-peak (R) is a fast transient <100 ms, which
contains frequency components >10 Hz in comparison to slower
waves. Using of high-pass filter highlight the energetic QRS
complex to determine sections with local maxima.
data=load('ECG_test_500Hz_v3.txt'); fs=500; % Hz data=data(1:30*fs,:); % 30s
t=linspace(0,(size(data,1)-1)/fs,size(data,1))';
II=data(:,2);
% Implement:
1) Band-pass filter 0,5-40 Hz
...
fII=filtfilt(bbp,abp,II);
2) Differentiate the signal. Compensate the shortening
by inserting the sample before signal (note. check
the transfer function of filter b=[-1 1], a=1).
dII=diff([fII(1); fII]);
3) Square differentiated signals and smooth it by the
moving average (MA) filter of 50ms window (envelope)
...
envelope=filtfilt(bMA,aMA,dII^.2);
4) Threshold the envelope (e.g. 10% of maximum) and
detect the onset and end of sections
th=0.1*max(envelope); % 10% of max. envelope
R_suspect=envelope>th; start=find(diff([0;R_suspect])>0); % 0+diff, >0 stop=find(diff([R_suspect;0])<0); % diff+0, <0
5) Find local maxima in QRS
for i=1:length(start) seg=fII(start(i):stop(i)); % ECG 0,5-40 Hz [~,pos]=max(seg); % index of maximum Rm(i)=start(i)+pos-1; % index after segment start end
2) Detect P, Q, S, T waves in each R-R interval. Implement of triangle-detector function and use it
to detect onsets and ends of the waves. Encapsulate the final function for all waves
parametrisation. Use it in a future exercise. 1) Make the triangle-detectro function (triangle_detector.m)
function [bx_max,S]=triangle_detector(segment)
ax=1; % x-position of vertex A ay=segment(ax); % y-position of vertex A cx=length(segment); % x-position of vertex C cy=segment(cx); % y-position of vertex C
% triangle area S=f(B) S=zeros(length(segment),1); for k=1:length(segment) % from A to C bx=k; % x-position of vertex B by=segment(k); % y-position of vertex B S(k)=0.5*abs((cx-ax)*(by-ay)-(cy-ay)*(bx-ax)); % area end [~,bx_max]=max(S); % x-position of vertex B correspond to the maximal area
2) In for-cycle test R-R intervals and parametrise all waves
for i=1:length(Rm)-1 seg=fII(Rm(i):Rm(i+1)-1); % R-R segment II 0,5-40 Hz % 1. derivation (local extreme=0 for continuous signal)
df=diff([seg(1); seg]); % decrease to increase change (local minimum for digital signals) sgn=sign(df); % wave S, Q
S=find(diff(sgn)>0,1); % first local minimum Q=find(diff(sgn)>0,1,'last'); % last local minimum
S Q
% wave T, P [~,T]=max(seg(S:floor(end/2))); % maximum between S and (R-R)/2 T=T+S-1; [~,P]=max(seg(floor(end/2):Q)); % maximum between (R-R)/2 and Q P=P+floor(length(seg)/2)-1;
% end of T-wave: find foot of wave using triangle-detector between
% T-maximum and half of R-R interval
Tend=triangle_detector(seg(T:floor(end/2))); Tend=Tend+T-1;
% onset of T-wave: find foot of wave using triangle-detector between % double of R-S interval (2*S) and T-maximum Tstart=triangle_detector(seg(2*S:T)); Tstart=Tstart+2*S-1;
% onset of P-wave: find a foot of wave using triangle-detector between
% half of R-R interval and P-maximum Pstart=...
% enf of P-wave: find foot of wave using triangle-detector between
% P-maximum and double Q-R interval before end of segment (end-2QR)
QR=length(seg)-Q;
Pend=triangle_detector(seg(P:end-2*QR)); Pend=...
% onset of Q-wave: find a foot of wave using
% triangle-detector between the end of P-wave and
% Q-maximum
Qstart=... % end of Q-wave: find the index of first crossing the
% amplitude of Q-onset
Qend=... % end of S-wave: find a foot of wave using triangle-
% detector between S-maximum and T-onset
Send=...
% Save the detection in indexes from start of ECG signal
Sm(i)=S+Rm(i)-1; Se(i)=Send+Rm(i)-1; Qs(i)=Qstart+Rm(i)-1; Qm(i)=Q+Rm(i)-1;
Qe(i)=Qend+Rm(i)-1; Ts(i)=Tstart+Rm(i)-1; Tm(i)=T+Rm(i)-1; Te(i)=Tend+Rm(i)-1; Ps(i)=Pstart+Rm(i)-1; Pm(i)=P+Rm(i)-1; Pe(i)=Pend+Rm(i)-1; end
P T
Qstrat
Q
Qend
R
II (
mV
)
time (s)
Send
Sm Ts
Tm
Te
Pm
Ps Pe
Qm
Qs
Se (J)
× Qe
3) Show all detection in ECG signal (II. lead) plot(t,fII); axis tight; hold on plot(t(Rm),fII(Rm),'or') plot(t(Sm),fII(Sm),'^r') plot(t(Se),fII(Se),'xr') ...
4) Encapsulate algorithm to function for future using! function [Ps,Pm,Pe,Qs,Qm,Qe,Rm,Sm,Se,Ts,Tm,Te]=my_ecg_fun(II,fs) ...
3) Use indexes for measuring ECG parameters. Remember, the order of detection in R-R interval
is R, S, T, P, Q, but interval measurement requires the heart cycle as P, Q, R, S, T. 1) Measure intervals and amplitudes
HR – heart rate per minute (BPM)
P – P-wave duration
PQ –P-Q interval, from P-onset to Q-onset
Q – Q-wave duration
QRSD – QRS complex duration, from Q-onset to S-end
QT –Q-T interval, from Q-onset to T-end
QTc – corrected QT by the HR, Bazett’s formula 𝑄𝑇𝑐𝐵 =𝑄𝑇
√𝑅𝑅⁄ ; where RR is R-R interval in
seconds
Amplitudes: P, R, T, and ST segment (S-end to T-onset) P_amp=median(fII(Pm)-fII(Ps));
...
ST_amp(i)=mean(fII(Se(i):Ts(i)));
2) Compute electrical heart exes for P, R, T waves.
Remember filter the I. and II. leads. fIII=fII-fI; faVf=(fII+fIII)/2; faVr=-(fI+fII)/2; faVl=(fI-fIII)/2;
% P-maximum can be under zero line in I. lead. Compute
the amplitude from isoline in P-onset
Paxis=median(-atand(-faVf(Pm)./(fI(Pm)-fI(Ps))));% 0-75° Raxis=median(-atand(-faVf(Rm)./fI(Rm))); % 0-120°
Taxis=median(-atand(-faVf(Tm)./fI(Tm))); % 15-75°
3) Show appropriate 10 seconds of all ECG leads in normalised time/amplitude
scale: 25mm/s and 10mm/1mV. For simple plotting use only one window, the
leads separate DC offset (2mV). Insert an amplitude/time referential
marker (1mV, 40ms, i.e. y=1cm, x=1mm). xr=25; % 25mm/s yr=10; % 10mm/mV xmm=[0 10]; % show 0-10s
ymm=[-12 2]; % show -12 mV až 2 mV
cmark=[zeros(round(0.04*fs),1);
ones(round(0.04*fs),1); % the marker 0.04s~25mm/s
zeros(round(0.04*fs),1)]; tmark=linspace(0,length(cmark)/fs,length(cmark)); % time axis of the marker
figure(); hold on plot(t,fI,'k'); xlim(xmm); plot(t,fII-2,'k'); xlim(xmm); % -2mV offset ...
plot(t,faVf-10,'k'); xlim(xmm); % -10mV offset
stairs(xmm(1)+tmark,cmark,'k','linewidth',2) stairs(xmm(1)+tmark,cmark-2,'k','linewidth',2); % -2mV offset ... stairs(xmm(1)+tmark,cmark-10,'k','linewidth',2); % -10mV offset
title('ECG 0.5-40 Hz')
xlabel(['time(s) [' num2str(xr) 'mm/s]']);
ylabel(['(mV) [' num2str(yr) 'mm/mV]']);
% grid of graph paper -------------------------------------------------------------
--
grid on; grid minor; % show main and minor grid axes=gca; % load graph properties
axes.YAxis.TickValues=ymm(1):0.5:ymm(2); % big square 0.5 mV (5mm) axes.XAxis.TickValues=xmm(1):0.2:xmm(2); % small square 200 ms (5mm)
axes.YAxis.MinorTickValues=ymm(1):0.1:ymm(2); % big square 0.1 mV (1mm) axes.XAxis.MinorTickValues=xmm(1):0.04:xmm(2); % small square 40 ms (1mm)
axes.YAxis.TickLabel=repmat({''},1,length(axes.YAxis.TickValues)); %y no-labels axes.YAxis.TickLabel(5:4:25)={'aVF','aVL','aVR','III','II','I'}; % leads’ names xtickangle(90); % 90° rotation of labels in x-axis
pbaspect(gca,[max(xmm)*xr (ymm(2)-ymm(1))*yr 1]) % normalized ratio of y-x axes
% text panel of measured properties
text(xmm(2),ymm(2),{... ['==LEAD II==']; ['HR=' num2str(HR,'%.1f') ' (55-90) BPM']; ...
},'VerticalAlignment','Top','EdgeColor','k','BackgroundColor','w');
4) Compute and show an average of ECG cycle in II. lead synchronized by R-peak. Compare manual measuring (e.g. ginput) to automatic analysis.
Parameter AUTO MANUAL NORM
HR 55-90
Duration (ms)
P <110
PQ 120-200
Q <30
QRSD <110
QT 250-500
Voltage (mV)
P 0-0.25
R 0.5-3
ST <±0.1
T >0