Noninvasive Fetal ECG: The PhysioNet/Computing in Cardiology Challenge 2013 1.0.0
(4,790 bytes)
function [out, MFRh] = QRSdetection(in, fs, mode)
% QRS detection based on Christov algorithm published in [1]
% (c) Jakub Kuzilek, Lenka Lhotska
% http://bio.felk.cvut.cz/~kuziljak/ E-mail: jakub.kuzilek@gmail.com
% Version: 1.0 Last update: 07/01/2013.
% (Version: 1.0, 07/01/2013)
%
%======================================================
%
% PURPOSE: This is main function of QRS detection algorithm based
% on Christovs detection algoritm and Independent Component
% Analysis.
%
% MANDATORY INPUT ARGUMENTS
% in ..... input data MxN, M - length of data, N - number of leads
% fs ..... sampling frequency in Hz
% mode ... 0 - Christov, 1 - Christov + ICA
% OPTIONAL INPUT ARGUMENTS
% none
% OUTPUT ARGUMENTS
% out .... time in samples of detected peaks
%=========================================================
%
% Related Bibliography:
%
% [1] Kuzilek J, Lhotska L. Electrocardiogram beat detection
% enhancement using independent component analysis. Medical
% Engineering and Physics. 2012.
%
%=========================================================
oin = in;
in = preprocessingQRSdetection(in, fs, mode); % preprocessing
N = length(in); % length of data
% help variables
MS200 = round(0.2*fs);
MS1000 = fs;
MS50 = round(0.05*fs);
MS350 = round(0.35*fs);
% constants
K1 = 0.36/MS1000;
K2 = -0.47/1.4/MS1000;
% init
M = 0.6*max(in(1:min([length(in),5*fs])));
MM = ones(1,5)*M;
mMM = M;
% F threshold, it does not depend on detected beats
F = zeros(1,N);
F(1:MS350) = mean(in(1:min([length(in),MS350])));
pom = zeros(MS50+1,N-MS50);
for m = 1:(N-MS50)
pom(:,m) = in(m:m+MS50);
end
pom = max(pom);
if(mode)
F(MS350:N-MS50) = cumsum([F(MS350),(pom(MS350+1:end)-pom(1:end-MS350))/290]); %500
else
F(MS350:N-MS50) = cumsum([F(MS350),(pom(MS350+1:end)-pom(1:end-MS350))/500]);
end
F(end-MS50:end) = F(end-MS50);
R = 0;
RR = [];
Rm = 0;
Rm23 = 0;
C = 1;
% detected QRS and help vars
QRS = zeros(1,1000);
iQRS = 1;
RRl = 0;
% last detected QRS time
tQRS = -200;
m = 0;
% history help
MFRh = zeros(1,N);
% Mh = zeros(1,N);
% Fh = zeros(1,N);
% Rh = zeros(1,N);
while m <= N-1
m = m+1;
% update weights
tdiff = m - tQRS;
if (tQRS > 0)
if(tdiff > MS200 && tdiff < MS1000+MS200)
M = mMM - K1*mMM*(tdiff-MS200);
elseif(tdiff > MS1000+MS200)
M = 0.6*mMM;
end
end
if(RRl && tdiff > Rm23 && tdiff < Rm)
R = K2*mMM*(tdiff-Rm23);
end
MFR = (M+F(m)+R)/C;
MFRh(m) = MFR;
% Mh(m) = M;
% Fh(m) = F(m);
% Rh(m) = R;
% decide if QRS found + update weights
if(m > tQRS + MS200 && in(m) > ((M+F(m)+R)/C)) % if sample is larger than threshold - QRS detected
[ampl, time] = max(in(m:min([m+MS200, N]))); % find peak amplitude
dQRS = m+time;
if(0.6*ampl > 1.5*MM(end)) % update MM and reset M threshold
MM = [MM, 1.1*MM(end)];
else
MM = [MM, 0.6*ampl];
end
MM = MM(2:end);
mMM = mean(MM);
M = mMM;
if(iQRS>=2) % if first RR interval can be calculated, start R calculation
if(RRl && (dQRS-tQRS)<0.4*RR(end) && (dQRS-tQRS)>1.2*RR(end)) % if detected RR is small or large than previous one
RR(end+1) = RR(end);
RR = RR(2:end);
elseif(RRl) % if RR is ok
RR(end+1) = dQRS-tQRS;
RR = RR(2:end);
else % add RR into storage
RR(end+1) = dQRS-tQRS;
if length(RR)==7
RRl=1;
end
end
R = 0;
Rm = sum(RR)/7;
Rm23 = Rm*0.6667;
end
% store QRS position
QRS(iQRS) = dQRS;
iQRS = iQRS + 1;
tQRS = dQRS;
C = 1;
end
% if QRS not detected for long period change coefficient C
if(C == 1 && RRl && tdiff > Rm*1.5)
m = max([tQRS 1]);
if mode
C = 1.3;
else
C = 2;
end
elseif(tdiff > MS1000 && C == 1)
m = max([tQRS 1]);
if mode
C = 1.3;
else
C = 2;
end
end
end
out = QRS(1:iQRS-1); % detected QRS peaks
for m = 1:length(out)
[~,t] = max(abs(oin(max([1,out(m)-60]):min([length(oin),out(m)+60]))));
out(m) = out(m)+ t -61;
end
d = diff(out);
% z = find(d<rng);
out(d<0.3*fs)=[];
out(out<1)=[];