ECG-Kit 1.0
(12,906 bytes)
%% (Internal) function reads the header of signal files
%
% heasig = readheader(hea_full_filename)
%
% Arguments:
%
% Input parameters: character string with hea_full_filename of header file
%
%
% Output:
%
% Output parameter: struct heasig with header information
%
%
% Example:
%
%
% See also read_ECG
%
% Authors:
% Salvador Olmos
% Last update Juan Bolea 07/10/2008
% adapted to the kit by Mariano Llamedo Soria (llamedom at {electron.frba.utn.edu.ar; unizar.es}
% Version: 0.1 beta
% Birthdate: 29/05/2014
% Last update: 29/05/2014
% Copyright 2008-2015
%
function heasig = readheader(hea_full_filename)
heasig = [];
fid = fopen(hea_full_filename,'rt');
if (fid <= 0) % Rute 11/08/2010
fid = fopen([hea_full_filename '.hea'],'rt');%Rute 11/08/2010
end
if (fid <= 0)
% heasig = [];
return;
% disp(['error in opening file ' hea_filename]);
end
[hea_path hea_filename hea_ext] = fileparts(hea_full_filename);
files = dir([hea_path filesep hea_filename '.*'] );
NotHea_idx = find(~strcmpi( [hea_filename hea_ext], {files(:).name}));
[~, max_idx] = max(cell2mat({files(NotHea_idx).bytes}));
if( isempty(max_idx) )
warning('readheader:NoECGfound', ['Could not found any ECG signal in the same path of ' hea_full_filename ])
ecg_filename = 'ECG_file_not_found';
else
ecg_filename = files(NotHea_idx(max_idx)).name;
end
% Used symbols to distinguish some fields of the header file
pp = ' /+:()x';
% First line reading
s = fgetl(fid);
% Remove blank or commented lines
while s(1) == '#'
s = fgetl(fid);
end
%% Record line
% Example: hea_filename'/'number_of_segments[opt] number_of_signals
% sampling_frequency[opt]'/'counter_frequency[opt]'('base_counter_value')'[opt]
% number_of_samples_per_signal[opt] base_time[opt] base_date[opt]
%%
% record hea_filename
[heasig.recname,s] = strtok(s,pp);
% multi-segment record
if strcmp(s(1),'/')
[s1 s] = strtok(s,pp);
heasig.nsegm = str2double(s1);
end
% number of signals
[s1 s] = strtok(s,pp);
heasig.nsig = str2double(s1);
if(heasig.nsig < 1 || heasig.nsig > 20 )
warning('readheader:AtypicalNsig', ['Atypical number of signals ' num2str(heasig.nsig) ])
if( heasig.nsig == 0 )
% NSRDB have nsig = 0
heasig.nsig = 1;
end
end
% sampling frequency (in samples per second per signal) [optional]
if ~isempty(s)
[s1 s] = strtok(s,pp);
heasig.freq = str2double(s1);
if heasig.freq > 0 && heasig.freq < 1
heasig.freq = 1/heasig.freq;
end
end
if isfield(heasig,'freq') % if exists sampling frequency field
if ~isempty(deblank(s))
if strcmp(s(1),'/')
[s1 s] = strtok(s,pp); % Counter frequency (in ticks per second) [optional]
heasig.cntfreq = str2double(s1);
if strcmp(s(1),'(') % (453) 765 834
[s1 s] = strtok(s,'('); % 453) 765 834
[s1 s] = strtok(s1,')'); % s1 = 453 s = ) 765 834
heasig.basecnt = str2double(s1); % Base counter value [optional]
[s1 s] = strtok(s,pp); % remove parentheses
heasig.nsamp = str2double(s1);
else
[s1 s] = strtok(s,pp); %20ABR2010 Juan
heasig.nsamp = str2double(s1); % number of samples per signal [optional]
end
else
[s1 s] = strtok(s,pp);
heasig.nsamp = str2double(s1); % number of samples per signal [optional]
if( heasig.nsamp == 0 )
% NSRDB have nsamp = 0
warning('readheader:AtypicalNsig', ['Atypical number of samples ' num2str(heasig.nsamp) ])
end
end
end
if isfield(heasig,'nsamp') % if exists number of samples per signal
if isempty(deblank(s)) || isempty(strfind(s,':'))
heasig.btime = '00:00:00';
heasig.bdate = '01/01/2000';
else
[s1 s] = strtok(s,':');
hour = strtrim(s1);
[s1 s] = strtok(s,':');
min = strtrim(s1);
[s1 s] = strtok(s,pp);
sec = strtrim(s1);
heasig.btime = [hour ':' min ':' sec];
if isempty(deblank(s)) || isempty(strfind(s,'/'))
heasig.bdate = '01/01/2000';
else
[s1 s] = strtok(s,'/');
day = strtrim(s1);
[s1 s] = strtok(s,'/');
month = strtrim(s1);
s1 = strtok(s,pp);
year = strtrim(s1);
% yy = datevec(['01/01/' year]);
heasig.bdate = [day '/' month '/' year];
end
end
end
end
if isfield(heasig,'nsegm')
%% Segment Specification Lines
%Example: record_name number_of_samples_per_signal
j = 1;
% addt = 0;
for i = 1:heasig.nsegm
s = fgetl(fid);
[segname{i},s] = strtok(s,pp);
if i > 1
heasig.sumsampsegm(i) = str2double(s)+heasig.sumsampsegm(i-1);
else
heasig.sumsampsegm(i) = str2double(s);
end
heasig.sampsegm(i) = str2double(s);
if ~strcmp(segname{i}(1),'~')
hsig{i} = readheader([hea_path filesep segname{i}]);
for k = 1:hsig{i}.nsig
desc{j} = strtrim(hsig{i}.desc(k,:));
j = j+1;
end
else
hsig{i}.null = 1;
hsig{i}.nsamp = heasig.sampsegm(i);
end
end
heasig.fname = char(segname);
heasig.desc = char(unique(desc));
heasig.hd = hsig;
% clear heasig;
% heasig = hsig;
else
%% Signal Specification Lines
%Example: file_hea_filename format'x'samples_per_frame[opt]':'skew[opt]'+'byte_offset[opt]
% ADC_gain[opt]'('baseline_ADC_units')'[opt]'/'units[opt]
% ADC_resolution[opt] ADC_zero[opt] initial_value[opt] checksum[opt]
% block_size[opt] description[opt]
%%
heasig.spf = ones(1,heasig.nsig);
heasig.baseline = zeros(1,heasig.nsig);
heasig.units(1:heasig.nsig) = {''};
heasig.fname = cell(heasig.nsig,1);
heasig.group = nan(heasig.nsig,1);
heasig.fmt = nan(heasig.nsig,1);
heasig.gain = nan(heasig.nsig,1);
heasig.adcres = nan(heasig.nsig,1);
heasig.adczero = nan(heasig.nsig,1);
heasig.initval = nan(heasig.nsig,1);
heasig.baseline = nan(heasig.nsig,1);
heasig.adczero = nan(heasig.nsig,1);
heasig.cksum = nan(heasig.nsig,1);
heasig.bsize = nan(heasig.nsig,1);
heasig.spf = nan(heasig.nsig,1);
heasig.desc = num2str((1:heasig.nsig)');
% Reading nsig lines, corresponding one for every lead
for i = 1:heasig.nsig
if( feof(fid) )
break
else
s = fgetl(fid);
end
% Remove blank or commented lines
while s(1)=='#'
if( feof(fid) )
break
else
s = fgetl(fid);
end
end
if( s(1)=='#' && feof(fid) ); break; end;
% file hea_filename
[heasig.fname{i},s] = strtok(s); %% Modificado 29/04/2008 old "[heasig.fname(i,:),s]=strtok(s,pp);"
[s1,s] = strtok(s,pp);
% % group
if i == 1
heasig.group(i) = 0;
else
if strcmp(heasig.fname(i,:),heasig.fname(i-1,:))
heasig.group(i)=0;
else
heasig.group(i) = heasig.group(i-1) + 1;
end
end
% format
[s3,s4]=strtok(s);
a=[strfind(s3,'x') strfind(s3,':') strfind(s3,'+')];
if isempty(a)
heasig.fmt(i)=str2double(deblank(s1));
else
[s2,s]=strtok(s);
a=[a length(s2)+1];
for k=1:length(a)-1
switch (s2(a(k)))
case 'x' % samples per frame [optional]
heasig.fmt(i)=str2double(s1);
heasig.spf(i)=str2double(s2(a(k)+1:a(k+1)-1));
case ':' % skew [optional]
heasig.fmt(i)=str2double(s1);
heasig.skew(i)=str2double(s2(a(k)+1:a(k+1)-1));
case '+' % byte offset [optional]
heasig.fmt(i)=str2double(s1);
heasig.offset(i)=str2double(s2(a(k)+1:a(k+1)-1));
end
end
end
[s1,s]=strtok(s); %% Modificado 29/04/2008 old "[s1,s]=strtok(s,pp);"
if ~isempty(deblank(s))
a=[strfind(s1,'(') strfind(s1,'/')];
%% Modificado 29/04/2008
if isempty(a) % ADC gain (ADC units per physical unit) [optional] -> units assumed mV
heasig.gain(i) = str2double(s1);
heasig.units{i} = 'mV';
else
[s2,s1] = strtok(s1,pp);
heasig.gain(i) = str2double(s2);
if ~isempty(s1)
a = strfind(s1,'/');
if isempty(a) % baseline (ADC units) [optional]
heasig.baseline(i) = str2double(s1(2:end-1));
% heasig.units(i,:) = 'mV';
else
if strcmp(s1(1),'(')
heasig.baseline(i) = str2double(s1(2:a-2));
f = s1(a+1:end);
heasig.units{i} = f; % units[optional]
else
heasig.baseline(i) = 0;
f = s1(2:end);
heasig.units{i} = f;
end
end
end
end
end
if isnan(heasig.gain(i))
heasig.gain(i) = 200;
else
if heasig.gain(i) == 0
heasig.gain(i) = 200;
end
if ~isempty(deblank(s))
s_aux = s;
[s1,s] = strtok(s,pp);
heasig.adcres(i) = str2double(s1); % ADC resolution (bits) [optional]
if isnan(heasig.adcres(i))
% failed to parse this field
s = s_aux ;
heasig.adcres(i) = 12;
elseif (heasig.adcres(i) == 0)
heasig.adcres(i) = 12;
end
end
if ~isnan(heasig.adcres(i))
if ~isempty(deblank(s))
s_aux = s;
[s1,s] = strtok(s,pp);
heasig.adczero(i) = str2double(s1); % initial value [optional]
if isnan(heasig.adczero(i))
% failed to parse this field
s = s_aux ;
end
end
end
if ~isnan(heasig.adczero(i))
if ~isempty(deblank(s))
s_aux = s;
[s1,s] = strtok(s,pp);
heasig.initval(i) = str2double(s1); % initial value [optional]
if isnan(heasig.initval(i))
% failed to parse this field
s = s_aux ;
end
end
end
if ~isnan(heasig.initval(i))
if ~isempty(deblank(s))
s_aux = s;
[s1,s] = strtok(s,pp);
heasig.cksum(i) = str2double(s1); % initial value [optional]
if isnan(heasig.cksum(i))
% failed to parse this field
s = s_aux ;
end
end
end
if ~isnan(heasig.cksum(i))
if ~isempty(deblank(s))
s_aux = s;
[s1,s] = strtok(s,pp);
heasig.bsize(i) = str2double(s1); % initial value [optional]
if isnan(heasig.bsize(i))
% failed to parse this field
s = s_aux ;
end
end
end
if ~isnan(heasig.bsize(i))
if ~isempty(strtrim(s))
heasig.desc(i,1:length(s))=s; % description [optional]
end
end
end
end
if isfield(heasig,'units')
heasig.units = char(heasig.units);
end
heasig.fname = char(heasig.fname);
end
fclose(fid);