Noninvasive Fetal ECG: The PhysioNet/Computing in Cardiology Challenge 2013 1.0.0

File: <base>/sources/joachim.behar_at_gmail.com/physionet2013.m (4,433 bytes)
function [FQRSout,QTout] = physionet2013(tm,ecg,paramStruct)
% template algorithm for Physionet/CinC competition 2013. This function can
% be used for events 1 and 2. Participants are free to modify any
% components of the code. However the function prototype must stay the same
% [FQRSout,QTout] = physionet2013(tm,ecg) where the inputs and outputs are specified
% below.
%
% inputs
%   tm :         Nx1 vector of time in milliseconds
%   ecg:         4x60000 (4 channels and 1min of signal at 1000Hz) matrix of
%                abdominal ecg channels.
%   paramStruct: param of the algorithm to use. if not inputed then the
%                default parameters are used. 
%                ***FOR SET-C of the challenge LEAVE EMPTY.***
% 
% output
%   FQRSout:    FQRS markers in seconds. Each marker indicates the position of one
%               of the FQRS detected by the algorithm.
%   QTout:      1x1 estimated fetal QTout duration
%
%
%
% Safe Foetus Monitoring Toolbox, version 1.0, Sept 2013
% Released under the GNU General Public License
%
% Copyright (C) 2013 Joachim Behar
% Oxford university, Intelligent Patient Monitoring Group - Oxford 2013
% joachim.behar@eng.ox.ac.uk
%
% Last updated : 02-08-2013
%
% This program is free software; you can redistribute it and/or modify it
% under the terms of the GNU General Public License as published by the
% Free Software Foundation; either version 2 of the License, or (at your
% option) any later version.
% This program is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
% Public License for more details.    

if nargin<2; error('physionet2013: wrong number of input arguments'); end;
if nargin<3; paramStruct=[]; end;
addpath(genpath('subfunctions/'));

try
    if isempty(paramStruct)
        % == for FQRS extraction
        paramStruct.method = 'FUSE';              % TS/TS-PCA/TS-EKF/DEFLATION/FUSE
        paramStruct.methodComplexity = 'COMPLEX'; % COMPLEX/SIMPLE
        paramStruct.smoothRR = 1;                 % postprocessing
        paramStruct.cinc_match = 1;               % twick to better match CinC scores
        paramStruct.debug = 0;
        paramStruct.fs = 1000;
        paramStruct.TSnbCycles = 20;              % nb of cycles to build template 
        paramStruct.EKFgain = 1;
        paramStruct.fhighNbCoeff = 5;
        paramStruct.fbasNbCoeff = 3;
        paramStruct.NotchCheck = 1;
        paramStruct.fbas = 10;
        paramStruct.fhigh = 99;
        paramStruct.STDcut = 29;                  % rubbish to fit to challenge scores (was 17)
        paramStruct.NbPC = 2;                     % nb of principal components in PCA
        paramStruct.detThres = 0.5;               % QRS detector threshold for FQRS
        paramStruct.qrsdet_wind = 15;             % qrs detection window: LENGTH_SEG/qrsdet_wind NEEDS TO BE AN INTEGER!!
        paramStruct.extract_qt = 0;
    end
    
    [FQRSout,~,outExtra] = physionet2013extract(tm,ecg,paramStruct);
catch ME
    for enb=1:length(ME.stack); disp(ME.stack(enb)); end;
    FQRSout=0.1:0.42:60;
    QTout=250;
end


try
    % == for QT extraction
    % the main reasons for doing the QT separately are:
    % (1) the baseline wander cutt-off must be lower than 10Hz otherwise
    % the T-wave is completely destroyed
    % (2) using BSS methods is not a good idea as part of the T-wave could
    % end in a secondary channel so we stay we time based methods.
    qt_paramStruct.method = 'TS-PCA';
    qt_paramStruct.methodComplexity = 'SIMPLE';  % MUST BE: SIMPLE (time based)
    qt_paramStruct.debug = 0; 
    qt_paramStruct.fs = 1000;
    qt_paramStruct.TSnbCycles = 20;
    qt_paramStruct.EKFgain = 1;
    qt_paramStruct.fhighNbCoeff = 5;
    qt_paramStruct.fbasNbCoeff = 3;
    qt_paramStruct.NotchCheck = 1;
    qt_paramStruct.fbas = 2; % a lower cut-off not to kill the T-wave
    qt_paramStruct.fhigh = 99;
    qt_paramStruct.NbPC = 2;
    qt_paramStruct.extract_qt = 1;    
    qt_paramStruct.rMQRS = outExtra.rMQRS; % use the MQRS returned by the previous step
    qt_paramStruct.rFQRS = outExtra.rFQRS; % use the FQRS returned by the previous step
    
    [~,QTout,~] = physionet2013extract(tm,ecg,qt_paramStruct);

catch ME
    for enb=1:length(ME.stack); disp(ME.stack(enb)); end;
    FQRSout=0.1:0.42:60;
    QTout=250;
end

end