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

File: <base>/sources/changjiang_7_at_163.com/genresults.m (7,765 bytes)
% MATLAB script for processing a Challenge 2013 data set with a Challenge entry
% Version 1.0  (13 February 2013)
%
% A script similar to this one will be used as part of the evaluation of
% Challenge entries written in m-code. We have provided these scripts so
% that Challenge participants can test their entries to verify that they
% run properly in the environment that will be used to test them.
%
% This script supplies a complete set of records, one at a time, to an
% entry, and collects its output for each record (a vector of  QRS
% annotations and an estimate of QT interval).
%
% If your entry is written in m-code, it must be in the form of a function
% named physionet2013, with this signature:
%         [fetal_QRSAnn_est,QT_Interval]=physionet2013(tm,ecgs)
%
% See the sample entry at http://physionet.org/challenge/2013/physionet2013.m
% for descriptions of the input and output variables.
%
% To use this script to obtain an unofficial score for your entry on set A:
%  1. Download these files from http://www.physionet.org/challenge/2013/ and
%     save them in your MATLAB working directory:
%	genresults.m		 (this file)
%       set-a-text.zip
%         or
%       set-a-text.tar.gz        (zip archive or tarball of set A CSV files)
%
%  2. Unzip set-a-text.zip (or unpack set-a.tar-text.gz), creating a
%     subdirectory within your working directory called 'set-a-text'.  When
%     you have completed this step, the set-a-text directory should contain
%     the individual signal files files (*.csv) as well as the reference
%     annotation files (*.fqrs.txt).
%
%  3. Save a copy of your entry (which should be named physionet2013.m) in
%     your working directory.  You can test this procedure using the sample
%     'physionet2013.m' we have provided, or you can use your own version.
%
%  4. The next few lines are MATLAB code that clears any previously set
%     variables, and sets the name of the directory containing the input
%     data, the name for the annotation/QT output files, and the name of
%     the files containing the known QRS intervals (*.fqrs).  Change them
%     if necessary.
%
% Note that if you run a test on a set more than once, this code will
% overwrite your output files!!

%Written by Ikaro Silva, 2013

clear all;close all;clc

% Suffix for fetal QRS annotation files produced by your entry
annotation_suffix='.fqrs_entry1';

% Suffix for reference fetal QRS annotation files supplied by PhysioNet
annotation_answer_suffix='.fqrs.txt';

% set_name is the name of the working directory containing the input
% CSV files.  Your entry's output annotation files will be written into
% this directory.  When you unpacked set A, the reference annotation
% files were also written in this working directory.  The reference
% annotation files will be inaccessible to your code while it is being
% evaluated using set B or set C.  The challenge is (in part) to produce
% annotation files that are as similar to the hidden reference annotation
% files as possible.
set_name='set-b-text'; % (change this to use other datasets)

rec_ext='.csv'; % (using the CSV dataset)

%QT Interval file: example of how to set the suffix in order to generate
% files for the QT interval (stored in the same location as the annotation
% files).
% NOTE that for this to work you will have to comment out or delete the 
% qt_suffix=''; line right below.

qt_suffix='.qt_entry1';

%NOTE: set qt_suffix to empty (as below) if you do not wisth to compete in this event
%this will stop the script from generating QT files int the same directory
qt_suffix='';


%Set 'show' to true to display the waveforms and their annotations
show=1;
clr={'k-','k-','k-','k-','b-'}; %Used for plotting only

fdel='/';
if(ispc)
    fdel='\';
end
cur_dir=pwd;
data_dir=[cur_dir fdel set_name fdel];

cd(data_dir)
records=dir(['*' rec_ext]);
cd(cur_dir)

I=length(records);
display(['Processing ' num2str(I) ' records ...'])


% Each Challenge .csv file (record) contains ECG data for one patient,
% in 5 columns (the timestamp and four abdominal_ecgs).  During each
% iteration of the loop below, the contents of a single record are
% loaded into arrays named tm and abdominal_ecgs. Your physionet2013.m
% then generates a set of annotations, fetal_QRSAnn_est, and an
% estimated QT interval that will be stored in files with the same
% record name but with suffixes defined by the values you have chosen
% above for 'annotation_sufix' and 'qt_suffix'. The output files are all
% kept in the same directory as the data (i.e., 'set-a-text' for set a).

header={'tm','ecgs'};
for i=1:I
    
    record_id=records(i).name(1:end-4);
    fname=[data_dir record_id rec_ext];
    fname_ann_out=[data_dir record_id annotation_suffix];
    fname_qt_out=[data_dir record_id qt_suffix];
    answers=[data_dir record_id annotation_answer_suffix];
    
    
    fid_in=fopen(fname,'r');
    if(fid_in == -1)
        error(['Could not open data file: ' fname]);
    else
        try
            %Read file header
            file_header=textscan(fid_in,'%s',2,'delimiter','\r\n');
            %Find number of channel
            NCH=length(regexp(file_header{1}{2}, ','))+1;
            %Get data
            format_str=repmat('%f ',[1 NCH]);
            ecgs=textscan(fid_in,format_str,'delimiter',',',...
                'TreatAsEmpty', {'-,', ',-,','-,'});
            cd(cur_dir)
            fclose(fid_in);
        catch exception
            fclose(fid_in);
            rethrow(exception);
        end
    end
    
    
    %Convert time to milliseconds
    ecgs=cell2mat(ecgs);
    tm=ecgs(:,1)*1000;
    ecgs(:,1)=[];
    
    
    % The contents of one input file are now ready to be given to your
    % physionet2013 function for analysis in the next line:
    
    %Get answers if the annotations are available
    QRSAnn=[];
    
    %Get the answers for this record file
    [fetal_QRSAnn_est,QT_Interval]=physionet2013(tm,ecgs);
    
    %Save annotations and QT answers to file
    try
        csvwrite(fname_ann_out,fetal_QRSAnn_est);
    catch exception
        warning(['Could not write file in: ' fname_ann_out])
        throw(exception)
    end
    if(~isempty(qt_suffix))
        try
            csvwrite(fname_qt_out,QT_Interval);
        catch exception
            warning(['Could not write file in: ' fname_qt_out])
            throw(exception)
        end
    end
    if(exist(answers,'file'))
        QRSAnn=dlmread(answers);
        if(~isempty(QRSAnn))
            %%TODO: uncomment once you have PhysioNet's scoring function
            % score=score2013(fetal_QRSAnn_est,QRSAnn,QT_Interval,QTAnn);
        end
    end
    
    % If 'show' was set to true above, display results for individual records
    if(show)
        [N,M]=size(ecgs);
        figure
        for m=1:M
            sig=ecgs(:,m);
            if(nansum(sig))
                sig=(sig-nanmean(sig))./(nanmax(sig)-nanmean(sig));
                xlim([0,5000]);
                plot(sig + (m-1)*2,clr{m});hold on;grid on
                plot(fetal_QRSAnn_est,sig(fetal_QRSAnn_est)+(m-1)*2,...
                    'o','MarkerSize',7,'MarkerEdgeColor','r','LineWidth',2)
                if(~isempty(QRSAnn))
                    plot(QRSAnn,sig(QRSAnn)+(m-1)*2,'x','MarkerSize',7,...
                        'MarkerEdgeColor','g','LineWidth',2)
                    lgd={'ECG','FQRS Estimate','FQRS Answer'};
                else
                    lgd={'ECG','FQRS Estimate'};
                end
                
            end
        end
        title(['Record id: ' record_id])
        xlabel('Time (ms)')
        legend(lgd)
    end
    
    if(~mod(i,5))
        display(['Processed: ' num2str(i) ' records out of ' num2str(I)])
    end
end

display(['Finished!!'])