function [position,positionaux,messages] = wavedet_3D(sig_all, ext_anot, heasig, messages ) %[position,positionaux,messages] =wavedet_3D(sigdir,headir,matdir,ecgnr,ft,anot,lead,t,qrs_flag,anot_fmt,aname,dirann) %Significant ECG points detector based on wavelet approach % %Input Parameters: % sigdir: directory of the original signal (.dat file) % headir: directory of the header file % matdir: output directory % ecgnr: string with the name of the record to analyze % ft: format file: % - 0 for MIT header using any recorded leads from same datafile % - 1 for LUND header (to be tested) % - 2 for data in matlab file (.mat file with a varible fa with sampling frequency and variable sinal with ecg, one lead per column) % - 4 for RawData.bin files (one hour) created with Mortara Software SuperECG % % obsolete formats % - 3 for MIT header using the Dower xyz (ft=0, leadsynth_flag=1) % - 10 for MIT format in PTBDB .dat extension file (ft=0) % - 30 for MIT type format in PTBDB .dat extension file use the projected xyz (ft=0, leadsynth_flag=1) % - 20 for MIT type format in PTBDB .xyz extension file (ft=0, leads=leads+12) % - 40 for MIT header using 3 PC based all available leads and signal (ft=0, leadsynth_flag=4,flagaux=0) % - 41 for MIT header using 3 PC based in 8 leads and sub interval on the beat (ft=40,leadsynth_flag=3,flagaux=1) % - 42 for MIT type format in PTBDB .dat extension file use the PC based all signal and 8 leads (ft=0,leadsynth_flag=3,flagaux=0) % - 44 for MIT header using for MIT type using lead aVF and 2 PC out of precordial leads and all signal (ft=0,leadsynth_flag=5,flagaux=0) % - 123 for RawData.bin files (one hour) created with Mortara Software SuperECG (ft=4) % - 124 for RawData.bin files (one hour) created with Mortara Software SuperECG use the projected xyz (ft=4, leadsynth_flag=1) % - 50 for MIT type format like in ft=0 file using the PC based all available leads and signal (ft=0, leadsynth_flag=4) % - 51 for MIT type format like in ft=0 file using the PC based in 8 leads and sub interval on the beat (ft=0,leadsynth_flag=3,flagaux=1) % - 52 for MIT type format like in ft=0 file use the PC based all signal and 8 leads (ft=40,leadsynth_flag=3,flagaux=0) % % anot: name of the annotation output file % lead: vector with the leads number to analyze (1,2 or 3 leads) % if lead is a cell array the first element stands for leads number to analyze from the ones read and % the second for the leads to be read from the original signal file % t=[tbegin tend]: time vector with initial and sample to analyze % flags: [qrs_flag leadsynth_flag flagaux] % qrs_flag: QRS detection only (2), External (1), internal (0) QRS detector (0 by default) % leadsynth_flag: None (0), (default) % Dower matrix derived VCG (1) % Levkov's matrix derived VCG (2) % Principal components based in 8 uncorrelated leads out of 12-lead standard (3) % Principal components based in all available leads (4) % lead aVF and Principal components based on precordial leads (5) % flagaux: use all signal (0) (default) or sub interval on the beat (1) for PC calculation, available only for leadsynth_flag>2 % % anot_fmt: cell with format in case of external annotation file % first field for QRS detector, format of annotation file: MIT (0) or mat file (1) % second field for with excluded segments: xls (0), MIT annotations (1) % aname: cell with annotation file name with QRS marks in the first field (by default ecgnr) % with annotation file name with excluded segments in the second field (by default aname{1}) % dirann: cell with directory with external annotation files (QRS marks and/or excluded segments, by default sigdir) % if diferent annotation files are used, first field refers to QRS marks and second field to excluded segments % %Output Parameters: % position: struct vector with the detected points locations in samples % % positionaux: struct vector with the detected points using each specified lead % - positionaux.position1: using lead(1) % - positionaux.position2: using lead(2) % - positionaux.position3: using lead(3) % % messages: struct vector with errors, warnings, setup and state % - messages.status=0,1; % - messages.errors % - messages.errors_desc % - messages.warnings % - messages.setup.wavedet.nsamp=nsamp; number of samples to process in each excerpt, consider to calculate some parameters (default 2^16/250*sf) % - messages.setup.wavedet.sig_quality: sig_quality test 1 or 0 (activated or inactivated) % % struct description: % Pon: P wave onset % P: P wave peak % Poff: P wave end % QRSon: QRS complex onset % Q: Q wave peak (in multilead, according to QRSonset best fitted lead) % R_inQRSon: R wave peak in QRSonset best fitted lead (multilead only) % R: R wave peak (median mark in multilead approach) % qrs: QRS complex fiducial mark % R_inQRSoff: R wave peak in QRSend best fitted lead (multilead only) % Rprima: R' wave peak (in multilead, according to QRSend best fitted lead) % S: S wave peak (in multilead, according to QRSend best fitted lead) % QRSoff: QRS complex end % Ton: T wave onset % T: first T wave peak (median mark in multilead approach) % Tprima: second T wave peak (in multilead, according to Tend best fitted lead) % Toff: T wave end % Ttipo: T wave morphology (1:5 corresponding respectively to normal, inverted, upwards only, downwards only, biphasc pos-neg, biphasc neg-pos) % Tscale: scale used for T wave detection % Ttipoon: T wave morphology, according to Tonset best fitted lead (multilead only) % Ttipooff: T wave morphology, according to Tend best fitted lead (multilead only) % % warnings description: % 'warning: there are not 8 uncorrelated leads, all available leads considered instead' % leadsynth_flag=3 was used over a file that does not have all precordial leads and at least 2 of the limb leads % leadsynth_flag=4 was automatically set % % 'warning: lead aVF not available, lead xpto considered instead' % leadsynth_flag=5 was used over a file that does not have a lead aVF nor 2 limb leads to calculate it % aVF was replaced by lead xpto % % 'warning: mV are assumed as units' % not units are provided, mV are assumed % % The analysis loop has an overlapping structure. The number of samples % processed is large and there are an overlap at the beginning and another % at the end. The first one is necessary because: a) the first l4-1 samples % are always incorrectly filtered b) To align the signals, as the filters % have different lengths, we must discard some samples. c) The algorithms % must have some possibility of turning back. % The second overlap is mainly because of the alignment, as the filters have % different delays. % % based on wavedet.m by Juan Pablo Mart�nez Cort�s % previous versions include wavedetplus.m and wavedet3D.m % Last update: Rute Almeida 07FEB2012 % % Designed for MATLAB Version R12; tested with MATLAB Version R13 ft = 2; str = '1'; positionaux=[]; position=[]; aname_sig_quality_cell{3} = []; t_initial=0; % Juan 28/03/2012 lead = 1; % if (nargin<14) % JB 27/07/2011 % % bufferedSignal = []; % Juan 28/03/2012 No se usan no tienen porque % % estar definidas % % bufferedHeaSig = []; % Juan 28/03/2012 % else % 03AGO 2011 % ft=NaN; % heasig = bufferedHeaSig; % % if ~isfield(heasig,'freq') % % messages.errors=[messages.errors {'Fatal error in wavedet_3D: no sampling frequency variable found.'}]; % % warning(char(messages.errors(end))) % % messages.errors_desc=[messages.errors_desc {'No sampling frequency variable found on the header information file.'}]; % % messages.status=0; % % return % % end % % if ~isempty(t) && length(t)==2 %& t(2)>t(1) % % if length(bufferedSignal) == t(2)-t(1)+1; % % sig_all =bufferedSignal(:,~isnan(bufferedSignal(1,:))); % % % t_initial=t(1); % Juan 28/03/2012 % % t=[1 length(sig_all)]; % % elseif length(bufferedSignal)>t(2) % % sig_all = bufferedSignal(:,t(1):t(2)); % % else % % sig_all = bufferedSignal; % % t=[1 length(sig_all)]; % % end % % else % % sig_all = bufferedSignal; % % t=[1 length(sig_all)]; % % end % % % % % if size(sig_all,2)>size(sig_all,1) % sig_all=sig_all'; % end % % if ~isfield(heasig,'nsamp') || isempty(heasig.nsamp) % heasig.nsamp=size(sig_all,1); % end % if ~isfield(heasig,'nsig') % heasig.nsig=size(sig_all,2); % end % if ~isfield(heasig,'gain') % heasig.gain=200.*ones(1,heasig.nsig); % When heasig.gain = 0 => default 200 % end % if ~isfield(heasig,'spf') % % heasig.spf=ones(1,max(heasig.nsig,leadreading)); % Juan % % 28/03/2012 leadreading no esta definido % heasig.spf=ones(1,max(heasig.nsig, size(sig_all,1))); % end % if ~isfield(heasig,'adczero') % heasig.adczero=zeros(1,heasig.nsig); % end % end t=[1 size(sig_all,1)]; %%%%%%%%%%%%%%%%%%%%%%% if nargin < 4 messages.warnings=[]; end if ~isfield(messages,'setup'), messages.setup.wavedet=[]; end if ~isfield(messages.setup.wavedet,'QRS_detection_only'), messages.setup.wavedet.QRS_detection_only=false; end if ~isfield(messages.setup.wavedet,'QRS_detection_thr'), messages.setup.wavedet.QRS_detection_thr=ones(5,1); end if ~isfield(messages,'errors'), messages.errors=[]; end if ~isfield(messages,'errors_desc'), messages.errors_desc=[]; end if ~isfield(messages,'warnings'), messages.warnings=[]; end if isfield(messages,'status') if messages.status~=1 messages.warnings=[messages.warnings {['Initial status=' num2str(messages.status) '. status changed to 1']}]; end end messages.status=1; messages.setup.wavedet.sig_quality = 2; % if nargin<7 %21MAR2011 % messages.errors=[messages.errors {'Fatal error in wavedet_3D: not enough inputs.'}]; % warning(char(messages.errors(end))) % messages.errors_desc=[messages.errors_desc 'Mandatory inputs not defined.']; % messages.status=0; % return % elseif nargin<9 % flags=[]; % end % if iscell(lead) % if size(lead,2)==2 % leadreading=(lead{2}); % else % leadreading=(lead{1}); % end % lead=lead{1}; % else % leadreading=(lead); % end % if nargin<=10 %&& anot_fmt==1 %JUL2011 % aname=ecgnr; % dirann=sigdir; % end%JUL2011 % if iscell(aname) % if length(aname)==2 % aname_sig_quality=aname{2}; % end % aname=aname{1}; % else % aname_sig_quality=aname; % end % if iscell(dirann) % if length(dirann)==2 % dirann_sig_quality=dirann{2}; % end % dirann=dirann{1}; % else % dirann_sig_quality=dirann; % end % if isempty(flags) % if isfield(messages.setup.wavedet,'qrs_flag') % flags(1)=messages.setup.wavedet.qrs_flag; % else % flags(1)=0; % end % elseif isfield(messages.setup.wavedet,'qrs_flag') && flags(1)~=messages.setup.wavedet.qrs_flag; % messages.warnings=[messages.warnings {'Obsolete use of flag with inconsistency: flag(1) value differs from messages.setup.wavedet.qrs_flag value. flag(1) ignored.'}]; % else % messages.setup.wavedet.qrs_flag=flags(1); % messages.warnings=[messages.warnings {['Obsolete use of flag. Use messages.setup.wavedet.qrs_flag=' num2str(flags(1)) 'instead.' ]}]; % end % if length(flags)<2 % if isfield(messages.setup.wavedet,'leadsynth_flag') % flags(2)=messages.setup.wavedet.leadsynth_flag; % else % flags(2)=0; % end % elseif isfield(messages.setup.wavedet,'leadsynth_flag') && flags(2)~=messages.setup.wavedet.leadsynth_flag; % messages.warnings=[messages.warnings {'Obsolete use of flag with inconsistency: flag(2) value differs from messages.setup.wavedet.leadsynth_flag value. flag(2) ignored.'}]; % else % messages.setup.wavedet.leadsynth_flag=flags(2); % messages.warnings=[messages.warnings {['Obsolete use of flag. Use messages.setup.wavedet.leadsynth_flag=' num2str(flags(2)) 'instead.' ]}]; % end % if length(flags)<3 % if isfield(messages.setup.wavedet,'flagaux') % flags(3)=messages.setup.wavedet.flagaux; % else % flags(3)=0; % end % elseif isfield(messages.setup.wavedet,'flagaux') && flags(3)~=messages.setup.wavedet.flagaux; % messages.warnings=[messages.warnings {'Obsolete use of flag with inconsistency: flag(3) value differs from messages.setup.wavedet.flagaux. flag(3) ignored.'}]; % else % messages.setup.wavedet.flagaux=flags(3); % messages.warnings=[messages.warnings {['Obsolete use of flag. Use messages.setup.wavedet.flagaux=' num2str(flags(3)) 'instead.' ]}]; % end % if length(flags)==4 % if isfield(messages.setup.wavedet,'nsamp') && messages.setup.wavedet.nsamp~=flags(4) % messages.warnings=[messages.warnings {'Obsolete use of flag with inconsistency: flag(4) value differs from messages.setup.wavedet.nsamp value. flag(4) ignored.'}]; % else % messages.setup.wavedet.nsamp=flags(4); % messages.warnings=[messages.warnings {['Obsolete use of flag. Use messages.setup.wavedet.nsamp=' num2str(flags(4)) 'instead.' ]}]; % end % end if( nargin < 2 || isempty(ext_anot) ) qrs_flag=0; else qrs_flag=1; end leadsynth_flag=0; flagaux=0; flags = [ qrs_flag leadsynth_flag flagaux]; messages.setup.wavedet.qrs_flag=qrs_flag; messages.setup.wavedet.leadsynth_flag=leadsynth_flag; messages.setup.wavedet.flagaux=flagaux; % if ~isfield(messages.setup.wavedet,'sig_quality') || messages.setup.wavedet.sig_quality==0 % messages.setup.wavedet.sig_quality=0; % messages.warnings=[messages.warnings {'No signal quality test used: messages.setup.wavedet.sig_quality=0'}]; % else % if isfield(messages.setup.wavedet,'dirann_sig_quality') % dirann_sig_quality=messages.setup.wavedet.dirann_sig_quality; % elseif ~exist('dirann_sig_quality','var') || isempty(dirann_sig_quality) % dirann_sig_quality=sigdir; % end % if isfield(messages.setup.wavedet,'aname_sig_quality') % aname_sig_quality=messages.setup.wavedet.aname_sig_quality; % elseif ~exist('aname_sig_quality','var') || isempty(aname_sig_quality) % aname_sig_quality=ecgnr; % end % messages.setup.wavedet.sig_quality=1; % messages.warnings=[messages.warnings {['Signal quality information used: messages.setup.wavedet.sig_quality=' num2str(messages.setup.wavedet.sig_quality)]}]; % end if length(flags)==3 if leadsynth_flag<3 flagaux=0; messages.warnings=[messages.warnings {'flagaux>0 only available for leadsynth_flag>2. flagaux=0 used'}]; end end %obsolete formats % if ft==3; % ft=0; leadsynth_flag=1; % end %obsolete formats % if ft==10 % ft=0; % end %obsolete formats % if ft==20 % ft=0; % lead=lead+12; % leadreading=leadreading+12; % end %obsolete format % if ft==30 % ft=0; % leadsynth_flag=1; % leadreading=1:12; % end%obsolete formats % if ft==41 % ft=0; % leadsynth_flag=3; % flagaux=1; % end %obsolete format % if ft==42||ft==52 % ft=0; % leadsynth_flag=3; % flagaux=0; % end%obsolete formats % if ft==50 % ft=0; % leadsynth_flag=4; % flagaux=0; % end%obsolete formats % if ft==51 % ft=0; % leadsynth_flag=4; % flagaux=1; % end%obsolete formats % if ft==123 % ft=4; % end% change format notation % if ft==124 % ft=4; % leadsynth_flag=1; % end% change format notation % if ft==44 % ft=0; % leadsynth_flag=5; % flagaux=0; % end%obsolete formats % if ft==40 % ft=0; % leadsynth_flag=4; % flagaux=0; % end%obsolete formats % % %number of leads from 1 to 3 % if length(lead)>3 % lead(4:end)=[]; % messages.warnings=[messages.warnings {['Too many leads to process, just first 3 leads are considered: lead=[' num2str(lead) ']']}]; % elseif isempty(lead) % lead=1; % leadreading=lead; % messages.warnings=[messages.warnings {'No leads indicated to process: first lead in file is considered'}]; % end % % if leadsynth_flag==1 % leadstring='synt'; % end % if leadsynth_flag==2 % leadstring='levk'; % end % if leadsynth_flag==1 || leadsynth_flag==2 % %%%%%%%%%%%%%%%%%%%%%%% % %verify leads to process % invalid_lead= find(lead>3); %#ok % if ~isempty(invalid_lead) % [C,IA,IB]=intersect(leadreading,lead); %#ok % Juan 28/03/2012 % if length(C)==length(lead) % lead=IA; % invalid_lead= find(lead>3); % Juan 28/03/2012 % if isempty(invalid_lead) % messages.warnings=[messages.warnings {['the lead(s) chosen to be processed are the lead(s) ' num2str(leadreading(lead))]}]; % else % alead=lead; % lead(invalid_lead)=[]; % if isempty(lead) % lead=1:min(length(lead),3); % end % messages.warnings=[messages.warnings {[ 'Invalid lead for VCG analysis (' num2str(alead) '): transformed lead(s) ' num2str(1:min(length(lead),3)) ' considered instead.' ]}]; % end % elseif ~isempty(C) % messages.warnings=[messages.warnings {[ 'Invalid lead for VCG analysis (' num2str(lead) '): transformed lead(s) ' num2str(leadreading(IA)) ' considered instead.' ]}]; % lead=IA; % else % messages.warnings=[messages.warnings {[ 'Invalid lead for VCG analysis (' num2str(lead) '): transformed lead(s) ' num2str(1:min(length(lead),3)) ' considered instead.' ]}]; % lead=1:min(length(lead),3); % end % end % %%%%%%%%%%%%%%%% % elseif leadsynth_flag==3 % invalid_lead=find(lead>8); % lead(invalid_lead)=[]; % if ~isempty(invalid_lead) % messages.warnings=[messages.warnings {'Invalid lead after the chosen PC transformation: 8 PC are produced.'}]; % end % elseif leadsynth_flag==4 % invalid_lead= find(lead>max(leadreading)); % Juan 28/03/2012 % lead(invalid_lead)=[]; % if ~isempty(invalid_lead) % messages.warnings=[messages.warnings {['Invalid lead after the chosen PC transformation: ' num2str(leadreading) ' PC are produced. Lead(s) ' num2str(lead) ' considered instead']}]; % end % if isempty(lead) % lead=1; % messages.warnings=[messages.warnings {['Invalid lead after the chosen PC transformation: lead=[' num2str(lead) '] considered instead.']}]; % end % % elseif leadsynth_flag==5 % if isempty(find(lead==1,1)) % messages.warnings=[messages.warnings { 'Processing lead 1, standing for aVF, is mandatory in the chosen PC transformation.'}]; % lead=[1 lead]; % end % invalid_lead=find(lead>7); % lead(invalid_lead)=[]; % if ~isempty(invalid_lead) % messages.warnings=[messages.warnings {'Invalid lead after the chosen PC transformation: aVF plus 6 PC are available.'}]; % end % if isempty(lead) % lead=1:3; % messages.warnings=[messages.warnings {['Invalid lead after the chosen PC transformation: lead=[' num2str(lead) '] considered instead.']}]; % elseif length(lead)>3 % lead(4:end)=[]; % messages.warnings=[messages.warnings {['Too many leads to process, just first 3 leads are considered: lead=[' num2str(lead) ']']}]; % elseif length(lead)==1 % messages.warnings=[messages.warnings { 'Single lead over lead aVF selected.' }]; % end % end % global OPT allfig=0;figuresoff=1; %#ok % OPT=optimset(@fminbnd); % OPT.MaxFunEvals=1000; % OPT.Display='off'; % warning off %#ok ultimo_anot=1; ultimo_anottyp=0; % timeoffset=0; % Juan 28/03/2012 Solo se define para el formato lund si % es necesario dentro count=0; %errores=struct('errores',[]); sep = filesep; % if isunix, %%%%%%% Rute 13/03/02 % sep = '/'; % else sep = '\'; %%%%%%% Rute 13/03/02 % end %%%%%%% Rute 13/03/02 PC_aux_ind=[]; % aux=find(ecgnr==sep); % headir=[headir ecgnr(1:aux)]; % sigdir=[sigdir ecgnr(1:aux)]; % matdir=[matdir ecgnr(1:aux)]; % if ~isempty(aux) % ecgnr=ecgnr(aux+1:end); % end %%%%%%%%%%%%%%%%%%%%%%% file format %%%%%%%%%%%%%%%%%%%%%%%%%%%% % if ft==0 % MIT format files % name=[headir sep ecgnr '.hea']; % heasig = readheader(name); % [auxleads] = ecgleads(heasig.desc); %V1 V2 V3 V4 V5 V6 I II III aVR aVL aVF X Y Z VX VY VZ % % %verify leads to read % if sum(leadreading>heasig.nsig)>0 % messages.warnings=[messages.warnings {[ 'The selected file contains only ' num2str(heasig.nsig) ' signals: unable to read leads [' num2str(leadreading) '], leads out of the range will be ignored' ]}]; % leadreading(leadreading>heasig.nsig)=[]; % end % % if leadsynth_flag==0 % should be leadreading=lead % if length(leadreading)~=length(lead) | (length(leadreading)==length(lead) & sort(leadreading)~=sort(lead)) %#ok % [C,IA,IB]=intersect(leadreading,lead); %#ok % if length(C)==length(lead) % extra leads on leadreading will be deleted % leadreading=IA; % messages.warnings=[messages.warnings {['the lead(s) chosen to be processed are the lead(s) ' num2str(leadreading)]}]; % else % extra leads on lead or different leads % if ~isempty(lead>heasig.nsig) % messages.warnings=[messages.warnings {[ 'The selected file contains only ' num2str(heasig.nsig) ' signals: unable to read leads [' num2str(lead) '], leads out of the range will be ignored' ]}]; % lead=lead(lead<=heasig.nsig); % end % if length(leadreading)~=length(lead) | (length(leadreading)==length(lead) & sort(leadreading)~=sort(lead)) %#ok % messages.warnings=[messages.warnings {[ 'unable to interpret the lead(s) number to process (' num2str(leadreading) '): lead(s) ' num2str(lead(lead<=heasig.nsig)) ' considered instead.' ]}]; % leadreading=lead; % end % end % else % messages.warnings=[messages.warnings {['the lead(s) chosen to be processed are the lead(s) ' num2str(leadreading)]}]; % end % elseif leadsynth_flag==1 || leadsynth_flag==2 || leadsynth_flag==3% Leads V1 to V6 and 2 limb leads required % if size(leadreading)<8 %wrong number of leads % if ~isnan(auxleads(1:8)) % leadreading=(auxleads(1:8)); % elseif ~isnan(auxleads([1:7 9])) % leadreading=(auxleads([1:7 9])); % elseif ~isnan(auxleads([1:6 8 9])) % leadreading=(auxleads([1:6 8 9])); % else % messages.errors=[messages.errors {'Fatal error in wavedet_3D: not enough leads in file to apply the chosen transformation.'}]; % warning(char(messages.errors(end))) % messages.errors_desc=[messages.errors_desc 'Leads V1 to V6 and 2 limb leads are required.']; % messages.status=0; % return % end % messages.warnings=[messages.warnings {['Not enough leads to apply the chosen transformation in given leadreading: leadreading=[' num2str(leadreading) '] considered instead' ]}]; % else % if sum(isnan(auxleads(1:6)))>0 || sum(isnan(auxleads(7:9)))>1 % heasig.desc does not include Leads V1 to V6 and 2 limb leads % if heasig.nsig>=8 % messages.warnings=[messages.warnings {'Leads V1 to V6 and 2 limb leads required to apply the chosen transformation but cannot be recognized. It is assumed that the first 8 leads of leadreading are V1 V2 V3 V4 V5 V6 I II'}]; % leadreading=leadreading(1:8); % auxleads=NaN*ones(size(auxleads)); % auxleads(1:8)=1:8; % else % messages.errors=[messages.errors {'Fatal error in wavedet_3D: not enough leads in file to apply the chosen transformation.'}]; % warning(char(messages.errors(end))) % messages.errors_desc=[messages.errors_desc 'Leads V1 to V6 and 2 limb leads are required.']; % messages.status=0; % return % end % else % heasig.desc includes Leads V1 to V6 and 2 limb leads % leadreading=leadreading(auxleads(auxleads<=length(leadreading)));% sort leadreding as V1 V2 V3 V4 V5 V6 I II III aVR aVL aVF X Y Z VX VY VZ % end % end % elseif leadsynth_flag==4 && size(leadreading)==1 % leadsynth_flag=0; % messages.warnings=[messages.warnings {'To aply PC transformation more than one lead is requires in leadreading: no trasnformation applied (leadsynth_flag=0)'}]; % elseif leadsynth_flag==5 && length(lead)~=1 % aVL and leads V1 to V6 required % if size(leadreading)<7 %wrong number of leads % if ~isnan(auxleads([12 1:6])) %lead aVF and V1 to V6 available % leadreading=auxleads([1:6 12]); % elseif ~isnan(auxleads(1:8)) % leadreading=auxleads(1:8); % elseif ~isnan(auxleads([1:7 9])) % leadreading=auxleads([1:7 9]); % elseif ~isnan(auxleads([1:6 8 9])) % leadreading=auxleads([1:6 8 9]); % else % messages.errors=[messages.errors {'Fatal error in wavedet_3D: not enough leads in file to apply the chosen transformation.'}]; % warning(char(messages.errors(end))) % messages.errors_desc=[messages.errors_desc 'Leads aVF and V1 to V6 are required. Sugestion: use leadsynth_flag=4 instead']; % messages.status=0; % return % end % else % if sum(isnan(auxleads(1:6)))>0 || (isnan(auxleads(12)) && sum(isnan(auxleads(7:9)))>1) % heasig.desc does not include Leads V1 to V6 and aVF cannot be calculated % if size(leadreading)==7 && heasig.nsig>=7 % messages.warnings=[messages.warnings {'Leads V1 to V6 and aVF limb leads required to apply the chosen transformation but cannot be recognized. It is assumed that the 7 leads of leadreading are V1 V2 V3 V4 V5 V6 aVF' }]; % leadreading=leadreading(1:7); % auxleads=NaN*ones(size(auxleads)); % auxleads([1:6 12])=1:7; % elseif heasig.nsig>=8 % messages.warnings=[messages.warnings {'Leads V1 to V6 and aVF limb leads required to apply the chosen transformation but cannot be recognized. It is assumed that the first 8 leads of leadreading are V1 V2 V3 V4 V5 V6 aVF' }]; % leadreading=leadreading(1:8); % auxleads=NaN*ones(size(auxleads)); % auxleads(1:8)=1:8; % else % messages.errors=[messages.errors {'Fatal error in wavedet_3D: not enough leads in file to apply the chosen transformation.'}]; % warning(char(messages.errors(end))) % messages.errors_desc=[messages.errors_desc 'Leads aVF and V1 to V6 are required. Sugestion: use leadsynth_flag=4 instead']; % messages.status=0; % return % end % else % heasig.desc includes Leads V1 to V6 and 2 limb leads % leadreading=leadreading(auxleads(auxleads<=length(leadreading)));% sort leadreding as %V1 V2 V3 V4 V5 V6 I II III aVR aVL aVF X Y Z VX VY VZ % end % end % elseif leadsynth_flag==5 && length(lead)==1 % if ~isnan(auxleads(12)) % leadreading=auxleads(12); % elseif sum(~isnan(auxleads(7:9)))>1 % leadreading=auxleads(~isnan(auxleads(7:9))); % elseif length(leadreading)==1 % messages.warnings=[messages.warnings {'Lead aVF lead is required but cannot be recognized. It is assumed that the first lead of leadreading is aVF'}]; % leadreading=1; % auxleads=NaN*ones(size(auxleads)); % auxleads(12)=1; % else % messages.warnings=[messages.warnings {'Lead aVF lead is required but cannot be recognized. It is assumed that the first 2 lead of leadreading are I and II'}]; % auxleads=NaN*ones(size(auxleads)); % auxleads(7:8)=1:2; % end % end % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% this is necessary when there are leads in different files. e.g. ptbdb database JP 2006 % leadsfile=NaN*ones(heasig.nsig,1); % leadinfile=NaN*ones(heasig.nsig,1); % nsiginfile=NaN*ones(heasig.nsig,1); % for jj=1:heasig.nsig % for kk=1:heasig.nsig % leadsfile(kk)=strcmp(heasig.fname(jj,:),heasig.fname(kk,:)); % end % leadsfile = cumsum(leadsfile); % leadinfile(jj) = leadsfile(jj); % lead indexes in the file % nsiginfile(jj) = leadsfile(end); % number of the leads in th file nsiginfile<=heasig.nsig % end % % if(min(lead)>nsiginfile(1)) % auxleads(auxleads<=nsiginfile(1))=NaN; % else % auxleads(auxleads>nsiginfile(1))=NaN; % end % n_auxleads=find(auxleads>0); % auxleads(n_auxleads)=leadinfile(auxleads(n_auxleads)); % % nsiginfile=nsiginfile(lead(1)); % Juan 28/03/2012 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%% % if (heasig.fmt(lead)==16) | (heasig.fmt(lead)==212) | (heasig.fmt(lead)==61), %#ok % %%%%%%% multilead%%% Rute 02.Dec.04 % if size(lead,2)==1 % formato = num2str(heasig.fmt(lead)); % elseif diff(heasig.fmt(lead))==0 % formato = num2str(heasig.fmt(lead(1))); % end % %%%%%%%%%%%%% % else % messages.errors=[messages.errors {'This format is not supported by the program.'}]; % warning(char(messages.errors(end))) % messages.errors_desc=[messages.errors_desc ['Format ' num2str(heasig.fmt(lead)) ' data. For MIT data, formats 16, 212 and 61 are supported.'] ]; % messages.status=0; % return % end % if strcmp(formato,'16')||strcmp(formato,'61'), % fid = fopen([sigdir heasig.fname(lead(1),:)],'rb'); % fseek(fid,0,-1); % Rewind the file % if strcmp(heasig.fname(1,1),'_'), % Siemens card recordings with MIT-type header % timeoffset=512; % fseek (fid, timeoffset,-1); % offset % end % end % % elseif ft==1 % LUND format files % try % hdsig=gethdsig(sigdir,ecgnr); % Reading header information % heasig = hdsig2heasig(hdsig); % leadinfile=lead; % % [auxleads] = ecgleads(heasig.desc); % catch me % messages.errors=[messages.errors {'Fatal error in wavedet_3D: unable to read header signal on Lund format.'}]; % warning(char(messages.errors(end))) % messages.errors_desc=[messages.errors_desc {me.message}]; % Juan 28/03/2012 % messages.status=0; % return % end % elseif ft==2 % data in a Matlab file % try % [sig_all,messages1,heasig] = readsignal(sigdir,ecgnr,t,ft,[],leadreading,messages); % Juan 28/03/2012 % if messages1.status==0 % error('Fatal error in wavedet_3D: unable to read signal on mat format.'); % Juan 28/03/2012 % end % catch me % messages.errors=[messages.errors {messages1.errors}]; % Juan 28/03/2012 % warning(char(messages.errors(end))) % messages.errors_desc=[messages.errors_desc {me.message}]; % Juan 28/03/2012 % messages.status=0; % return % end % if size(sig_all,2)>size(sig_all,1) % sig_all=sig_all'; % end % %should not be needed; I will remove that part, all of that is done in % %readsignal Juan 28/03/2012 % if ~exist('heasig','var') % heasig.nsamp=size(sig_all,1); % try % if exist('fa','var') % heasig.freq=fa; %#ok % else % heasig.freq=messages.setup.wavedet.freq; % end % catch me % messages.errors=[messages.errors {'Fatal error in wavedet_3D: no sampling frequency variable found.'}]; % warning(char(messages.errors(end))) % me.message = 'No sampling frequency variable found on the mat file.'; % Juan 28/03/2012 % messages.errors_desc=[messages.errors_desc {me.message}]; % Juan 28/03/2012 % messages.status=0; % return % end % heasig.nsig=size(sig_all,2); % heasig.gain=200.*ones(1,heasig.nsig); % When heasig.gain = 0 => default 200 % heasig.adczero=zeros(1,heasig.nsig); % end % %%%%%%%%%%%%%%%%%%%%%%% % % leadinfile=lead; % % nsiginfile=heasig.nsig; %Juan 28/03/2012 % heasig.spf_ecg=1; % % if isfield(heasig,'desc') % [auxleads] = ecgleads(heasig.desc); % else % auxleads = 1:heasig.nsig; % assuming that all are ECG % end % % elseif ft==4 % Ana e Tiago 11-04-2006 (copy from wavedetplus) % fa=1000; % % aux=[sigdir ecgnr '.bin']; Juan 28/03/2012 % if nargin >=8, % if isempty(t) % t=[1 fa*60*60]; % % else % % t=[t(1) min(t(1)+fa*60*60,t(2))]; % end % else % t=[1 fa*60*60]; % end % % first_sample=t(1); %ver com Sonia se '1 -1 pq first_sample=0 por % % defeito!!!! Juan 28/03/2012 % % n_sample_per_lead=t(end);Juan 28/03/2012 % % lead_number=lead;Juan 28/03/2012 % heasig.nsamp=t(2)-t(1); % %%%%%%%%%%%%%%%%%%%%%%%%%%% % heasig.freq=fa; % heasig.gain=200; % heasig.nsig=12; % heasig.units=char(ones(heasig.nsig,1)*'microV'); % heasig.desc=['I ';'II ';'V1 ';'V2 ';'V3 ';'V4 ';'V5 ';'V6 ';'III';'aVR';'aVL';'aVF']; % [auxleads] = ecgleads(heasig.desc); % leadinfile=lead; % % nsiginfile=heasig.nsig; % % elseif isnan(ft) % data in buffer % 03AGO 2011 % leadinfile=lead; % % nsiginfile=heasig.nsig; Juan 28/03/2012 % heasig.spf_ecg=1; % if ~isfield(heasig,'nsamp') || heasig.nsamp<=0 % heasig.nsamp=size(sig_all,1); % end % if isfield(heasig,'desc') % [auxleads] = ecgleads(heasig.desc); % else % auxleads = 1:heasig.nsig; % assuming that all are ECG % end % else % try % [sig_all,messages1,heasig] = readsignal(sigdir,ecgnr,t,ft,[],leadreading,messages); % if messages1.status==0 % error('Fatal error in wavedet_3D: no admissible format.'); % Juan 28/03/2012 % end % catch me % messages.errors=[messages.errors {messages1.errors}]; % me.message = 'Format ft should be one of {0,1,2,4}. See help wavedet3D for details.'; % Juan 28/03/2012 % warning(char(messages.errors(end))) % messages.errors_desc=[messages.errors_desc {me.message}]; % Juan 28/03/2012 % messages.status=0; % return % end % if size(sig_all,2)>size(sig_all,1) % sig_all=sig_all'; % end % end % leadinfile=lead; % Juan 28/03/2012 definido dentro de cada formato % nsiginfile=heasig.nsig; % Juan 28/03/2012 parece que no se usa m�s no es % necesario definir if ~isfield(heasig,'spf') heasig.spf=ones(1,heasig.nsig); end % try % heasig.spf_ecg=heasig.spf(leadinfile(1)); % catch me % me.message = 'It is taken the first lead in file.'; % messages.warnings = [messages.warnings {me.message}]; % heasig.spf_ecg=heasig.spf(1); % end heasig.spf_ecg = 1; messages.setup.wavedet.freq=heasig.spf_ecg*heasig.freq; %13ENE2010 % if isfield(heasig,'desc') % [auxleads] = ecgleads(heasig.desc); % else % auxleads = 1:heasig.nsig; % assuming that all are ECG % end % at this point heasig must exist if isfield(messages.setup.wavedet,'nsamp') nsamp = messages.setup.wavedet.nsamp; % Number of samples per excerpt for the WT as input else nsamp=0; end if nsamp==0 nsamp = 2^16/250*messages.setup.wavedet.freq; % Number of samples per excerpt for the WT corresponding to 2^16 samples at sf=250 end messages.setup.wavedet.nsamp=nsamp; % if nargin >=8, % if isempty(t) % t=[1 heasig.nsamp]; % pode falhar em formato lund... % else % t(1)=max(t(1),1); % if ~isempty(heasig.nsamp) % t(2)=min(t(1)+heasig.nsamp-1,t(2)); % end % end % else % t=[1 heasig.nsamp]; % end t=[1 heasig.nsamp]; % if flagaux==1 % if isfield(messages.setup.wavedet,'leadsynth') % leadref= messages.setup.wavedet.leadsynth; % messages.warnings=[messages.warnings {'Lead' num2str(leadref) ' will be considered for PCA time interval.'}]; % else % if ~isnan(auxleads(8)); %lead II % leadref=auxleads(8); % else % messages.warnings=[messages.warnings {'Lead II not available. First selected lead would be considered instead.'}]; % warning(char(messages.warnings(end))); % leadref=lead(1); % end % end % if ~exist([matdir ecgnr '.s' num2str(leadref)],'file') % wavedet_3D(sigdir,headir,matdir,ecgnr,ft,['s' num2str(leadref)],leadref); % end % marks=readannot([matdir ecgnr '.s' num2str(leadref)]); % if exist('marks','var') % marks=posmat2(marks); % marks(marks==0)=NaN; % end % PC_aux_ind= []; % tol1=0;tol2=0; tol3=200; % % mark_on=4;mark_off=10;mark_on2=5; mark_off2=6; % QRSonset-tend % % mark_on=7;mark_off=10;mark_on2=6;mark_off2=10; % ton-tend % % mark_on=8;mark_off=10;mark_on2=6;mark_off2=10;% tpeak-tend % % mark_on=4;mark_off=6;mark_on2=4;mark_off2=6;% QRS based % % for tt=1:size(marks,1) % if ~isnan(marks(tt,mark_off)) & ~isnan(marks(tt,mark_on))%#ok % % PC_aux_ind=[PC_aux_ind round((marks(tt,mark_on)-tol1)):round((marks(tt,mark_off)+tol2))]; %#ok % elseif ~isnan(marks(tt,mark_on))& ~isnan(marks(tt,mark_off2))%#ok % % PC_aux_ind=[PC_aux_ind round((marks(tt,mark_on)-tol1)):(marks(tt,mark_off2)+tol3)]; %#ok % elseif ~isnan(marks(tt,mark_on2))& ~isnan(marks(tt,mark_off))%#ok % % PC_aux_ind=[PC_aux_ind round((marks(tt,mark_on2)-tol3)):(marks(tt,mark_off)+tol2)]; %#ok % else % PC_aux_ind=[PC_aux_ind round((marks(tt,5)-tol3)):(marks(tt,5)+tol3)]; %#ok % end % end % else % PC_aux_indaux= 1:(t(2)-t(1)+1); %EXARLE OJO %PC_aux_indaux=[];%alternativa % end % try % heasig.gain(heasig.gain==0)=200; % When heasig.gain = 0 => default 200 % catch me % me.message = 'Signal gain is set to 200'; % Juan 28/03/2012 % messages.warnings = [messages.warnings {me.message}]; % Juan 28/03/2012 % end % Reading of external QRS annotation file if qrs_flag % if qrs_flag==1 % The QRS fiducial point is read from external annotator % switch (anot_fmt); % case 0 % MIT annotation file % if exist([dirann filesep aname],'file')%Jul2011 % Jbolea 01/12/11 % s=readannot([dirann aname],t); % s=isqrs(s,heasig,t); % ext_anot=s.time'; % else error('QRS annotation file not found'); % end % case 1 % mat file % if exist([dirann aname],'file')%Jul2011 % % if exist([dirann aname '.mat'],'file')%Jul2011 % % try % s= readannot_mat(dirann, aname,'tm_qrs');%OCT2012 % s.tm_qrs.pos = round(s.tm_qrs.pos*heasig.freq/1000); % ext_anot=s.tm_qrs.pos(s.tm_qrs.pos >= t(1)&s.tm_qrs.pos <= t(2));%OCT2012 % catch % % s= readannot_mat(dirann, aname,'qrs');%DEC2011 % s.qrs.pos = round(s.qrs.pos*heasig.freq/1000); % ext_anot=s.qrs.pos(s.qrs.pos >= t(1)&s.qrs.pos <= t(2));%Jul2011 % Jbolea 01/12/11 % end % % aux_t=t/heasig.freq/60/60; %%%???? ver heasig.freq % Juan % % 28/03/2012 % % %s=load ([dirann aname]); % %kk=getfield(s);%JUL2011 % % eval(['ext_anot=s.qrs;']); % else error('QRS annotation file not found'); % end % otherwise % messages.warnings=[messages.warnings {'Bad annotation format for external QRS annotation file; internal annotator would be considered instead.'}]; % warning(char(messages.warnings(end))); % qrs_flag=0; % end % end % messages.setup.wavedet.qrs_flag=qrs_flag; messages.setup.wavedet.leadsynth_flag=leadsynth_flag; messages.setup.wavedet.flagaux=flagaux; %%%%%%%%%%%%%%%%%%%%%%% Initiliazation %%%%%%%%%%%%%%%%%%%%%%%%%%%% inisamp = t(1); endsamp = t(1)-1; %15MAR09 timeqrs1 = [];timeqrs2 = [];timeqrs3 = []; lastqrs1 = 1;lastqrs2 = 1;lastqrs3 = 1; if qrs_flag==0 || qrs_flag==2 % estimated maximum number of beats maxlength = round((t(2)-t(1))/messages.setup.wavedet.freq*3); else maxlength=length(ext_anot); end if qrs_flag==1, % sel=find(ext_anot %%%%% Protection 25/08/2010 inisamp = round(inisamp); endsamp = round(endsamp); % display(['File Evolution (analyzing): ' timestr(round(inisamp/messages.setup.wavedet.freq*1000))... % ' to ' timestr(round(endsamp/messages.setup.wavedet.freq*1000))]); nsamp = round(nsamp); %%%%%%%%%%%%%%%%%%%%%%% loading ECG signal %%%%%%%%%%%%%%%%%%%%%%%%%%%% if isnan(ft)||ft==0||ft==1||ft==2||ft==4||ft>4 % if ft==0||ft==4 || ft==1 %MIT , Lund, Mortara %21MAR2011 % [sig,messages1,heasig] = readsignal(sigdir,ecgnr,[inisamp endsamp],ft,heasigreading,leadreading,messages); % read leadreading % if messages1.status==0 % messages.errors=[messages.errors messages1.errors]; % warning(char(messages.errors(end))) % messages.errors_desc=[messages.errors_desc messages1.errors_desc]; % messages.status=0; % return; % else % messages.warnings=[messages.warnings messages1.warnings ];%Jul2011 % if ~isfield(messages.setup,'readsignal') || ~isfield(messages.setup.readsignal,'file') % messages.setup.readsignal.file=messages1.setup.file; % end % if ~isfield(messages.setup.readsignal,'t') % messages.setup.readsignal.t=messages1.setup.t; % else % messages.setup.readsignal.t(2)=messages1.setup.t(2); % end % if ~isfield(messages.setup.readsignal,'nsig'), messages.setup.readsignal.nsig=messages1.setup.nsig; end % end % else % sig=sig_all(inisamp-t(1)+1:min(endsamp-t(1)+1,size(sig_all,1)),:); % end sig=sig_all(inisamp-t(1)+1:min(endsamp-t(1)+1,size(sig_all,1))); % if size(sig,1)==length(leadreading) % Jbolea 21/03/2011 % sig=sig'; % end % % n_auxleads=find(auxleads>0); %#ok % if isfield(heasig,'units') % for auxlead=1:length(leadreading) % % if strcmp(deblank(upper(heasig.units(leadreading(auxlead),:))),'MV')||strcmp(deblank(upper(heasig.units(leadreading(auxlead),:))),'MILLIVOLTS')||... % strcmp(deblank(upper(heasig.units(leadreading(auxlead),:))),'MILIVOLTIOS') % sig(leadreading(auxlead),:) = sig(leadreading(auxlead),:)*1e3; % conversion to microV % messages.warnings=[messages.warnings {'signal units changed: converted from milivolts to microvolts'}]; % warning(char(messages.warnings(end))) % heasig.units=(char(ones(heasig.nsig,1)*'microvolts')); % Jbolea 21/3/2011 % elseif strcmp(deblank(upper(heasig.units(leadreading(auxlead),:))),'nV')||strcmp(deblank(upper(heasig.units(leadreading(auxlead),:))),'NANOVOLTS')||... % strcmp(deblank(upper(heasig.units(leadreading(auxlead),:))),'NANOVOLTIOS') % sig(:,leadreading(auxlead)) = (sig(:,leadreading(auxlead)))/1e3; % conversion to microV % messages.warnings=[messages.warnings {'signal units changed: converted from volts to microvolts'}]; % warning(char(messages.warnings(end))) % heasig.units=(char(ones(heasig.nsig,1)*'microvolts')); % elseif strcmp(deblank(upper(heasig.units(leadreading(auxlead),:))),'V')||strcmp(deblank(upper(heasig.units(leadreading(auxlead),:))),'VOLTS')||... % strcmp(deblank(upper(heasig.units(leadreading(auxlead),:))),'VOLTIOS') % sig(leadreading(auxlead),:) = (sig(leadreading(auxlead),:))*1e6; % conversion to microV % messages.warnings=[messages.warnings {'signal units changed: converted from volts to microvolts'}]; % warning(char(messages.warnings(end))) % heasig.units=(char(ones(heasig.nsig,1)*'microvolts')); % end % end % else % for auxlead=1:length(leadreading) % % sig(leadreading(auxlead),:) = sig(leadreading(auxlead),:).* 1e3; %% by default % end % messages.warnings=[messages.warnings {'no signal units given: milivolts assumed'}]; % warning(char(messages.warnings(end))) % messages.warnings=[messages.warnings {'signal units changed: converted from milivolts to microvolts'}]; % warning(char(messages.warnings(end))) % heasig.units=(char(ones(heasig.nsig,1)*'microvolts')); % end % if leadsynth_flag==1||leadsynth_flag==2 % % if isnan(auxleads(8)) %lead II is not available % sinal= leadcalc([sig(:,auxleads(1:7)) sig(:,auxleads(7))+sig(:,auxleads(9)) ],leadstring ); %Juan 23/06/2011 % else % sinal= leadcalc(sig,leadstring); % end % sig=sinal(:,~isnan(sinal(1,:)))'; % elseif leadsynth_flag==3||leadsynth_flag==4||leadsynth_flag==5 % PC based delineation % if leadsynth_flag==4 % PCleads=1:size(sig,2); % considering all available leads % elseif leadsynth_flag==3 % considering 8 uncorrelated leads % if ~isnan(auxleads(1:7)) & (~isnan(auxleads(8))||~isnan(auxleads(9))) %#ok % if isnan(auxleads(8)) %lead II is not available % PCleads=[1:7 9]; %leads defined in leadreading, plus constructed lead II % sig(:,end+1)=sig(:,7)+sig(:,8); %#ok % else % PCleads=1:8; %leads are already defined in leadreading % end % else % messages.warnings=[messages.warnings {'There are not 8 uncorrelated leads, all available leads considered instead'}]; % warning(char(position.warningss(end))); % PCleads=1:size(sig,2); % leadsynth_flag=4; % end % elseif leadsynth_flag==5 % if length(lead)>1 % considering precordial uncorrelated leads % PCleads=2:7; %leads defined in leadreading, plus aVF % else % PCleads=[]; % end % end % if ~exist('PC_aux_ind','var') || isempty(PC_aux_ind) % PC_aux_indaux= 1:length(sig); % else % if flagaux == 1 % PC_aux_indaux=PC_aux_ind(PC_aux_ind>=firstnewsamp & PC_aux_ind<=endsamp)-firstnewsamp+1; % end % end % %no NaN allowed in sig 29JUN2011 % indx = find(isnan(sig(:,1)) == 1); % if ~isempty(indx) % sig(indx,:) = sig(indx-1,:); % end % % [eigvectors,eigvalues]=eig(cov(sig(PC_aux_indaux,PCleads))); % [s_eigvalues,order]=sort(diag(eigvalues)); %#ok % %pc=(eigvectors(:, order(end:-1:(end-length(lead)+1))))'*sig(:,PCleads)'; % pc=(eigvectors(:, order(end:-1:(end-2))))'*sig(:,PCleads)'; %11JUL2011 % if leadsynth_flag==5 % if isnan(auxleads(12)) %lead aVF is not available % if ~isnan(auxleads(7)) && ~isnan(auxleads(8)) % sig=[sig(:,auxleads(8))-1/2*sig(:,auxleads(7)) pc(1:min(2,(length(lead)-1)),:)']; % elseif ~isnan(auxleads(7)) && ~isnan(auxleads(9)) % sig=[sig(:,auxleads(9))+1/2*sig(:,auxleads(7)) pc(1:min(2,(length(lead)-1)),:)']; % elseif ~isnan(auxleads(8)) && ~isnan(auxleads(9)) % sig=[1/2*(sig(:,auxleads(8))+sig(:,auxleads(9))) pc(1:min(2,(length(lead)-1)),:)']; % else % lead=auxleads(find(~isnan(auxleads([7:end 1:6])))); %#ok % messages.errors=[messages.errors {'lead aVF not available, PC based on precordial leads used only'}]; % warning(char(messages.errors(end))); % sig= pc(1:min(3,(length(lead)-1)),:)'; % leadsynth_flag=4; % end % elseif length(lead)>1 % sig=[sig(:,7) pc']; % sig=sig(:,lead); % end % else % sig=pc(lead,:)'; % end % else %leadsynth_flag==0: should be leadsreading=lead % if lead<=size(sig,2) % sig=sig(:,lead); %leadinfile=leadinfile(lead); % try % messages.warnings=[messages.warnings {[ 'the lead(s) chosen to be processed are the lead(s)' num2str(leadreading(lead))]}]; % catch me % me.message = 'Error including warning information'; % end % else % if leads are in leadreading % [C,IA,IB]=intersect(leadreading,lead); %#ok % if length(C)==length(lead) % sig=sig(:,IA); % messages.warnings=[messages.warnings {['the lead(s) chosen to be processed are the lead(s) ' num2str(leadreading(IA))]}]; % lead=leadreading(IA); %7ABRIL2011 % else %should not append % lead=leadreading(1:min(3,end)); % messages.warnings=[messages.warnings {[ 'unable to interpret the lead(s) number to process (' num2str(lead) '): lead(s) ' num2str(leadreading) ' considered instead.' ]}]; % end % end % end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Modificado Juan 9/03/11 Rute 9May2011 if size(sig,2)>1 str = ''; else str = '1'; end %%%%%%%%%%%%%%%%%%%%%%% WT construction and parameters setting %%%%%%%%%%%%%%%%%%%%%%%%%%%% if messages.setup.wavedet.filter_bank_design==0;% RUTE 24NOV2011 wt = wavt5(sig(:,1)',q1,q2,q3,q4,q5); % WT equivalent filtering % 22/05/02 Rute including scale 5 wt=wt(l5:end,1:5); % Remove "incorrect" samples samp = (inisamp + l5 -1):endsamp-d5; % First l5-1 samples are not correctly filtered (border effect) % Last d5 samples are discarded in order to alineate all the % filtered signals, taking into acount the filter delays % Synchronizing filtered signals at different scales w1 = zeros(size(wt,1)-d5,5); w1(:,5) = wt(d5+1:end,5); w1(:,4) = wt(d4+1:end+d4-d5,4); w1(:,3) = wt(d3+1:end+d3-d5,3); w1(:,2) = wt(d2+1:end+d2-d5,2); w1(:,1) = wt(d1+1:end+d1-d5,1); else % RUTE 24NOV2011 wtECG = qs_wt(sig,1:5, messages.setup.wavedet.freq, q_filters);% RUTE 24NOV2011 ver pf clear w1 w1(1:size(wtECG,1),1:5) = wtECG(:,1,:);% RUTE 24NOV2011 samp =inisamp:endsamp;% RUTE 24NOV2011 l5=1;d5=0; end interval_to_processed=[inisamp+l5+1 endsamp-d5]; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%check quality of the signal swt=w1.^2; % Initialization of the thresholds for QRS detection (eps) %step= messages.setup.wavedet.freq; %internal % if messages.setup.wavedet.sig_quality==2 %internal % step=heasig.spf_ecg*heasig.freq; %internal % indexes = signaltest(w1(:,1),step,1,sqrt(mean(swt(:,1)))); % indexes(indexes>length(w1))=[]; % % if ~isempty(indexes) % segments= indexes([find(diff(indexes)~=1) 1+find(diff(indexes)~=1)])'; % segments=[indexes(1) segments(:)' indexes(end)]; % segments=reshape(segments,2,length(segments)/2)'-d5-l5+1+t(1)+fileevolution(1)-2; % nsegments=size(segments,1); % resultados2xls(char(ones(nsegments,1)*ecgnr),[ones(nsegments,1)*[ft lead(1)] segments],[dirann_sig_quality aname_sig_quality '_sig_quality'],date); % end % elseif messages.setup.wavedet.sig_quality==1 %external % if ~iscell(aname_sig_quality) % aname_sig_quality_cell{1}=aname_sig_quality(:,1); % end % anots = readannot_mat(dirann_sig_quality,aname_sig_quality_cell{1},'no_quality_segments'); % data = [anots.no_quality_segments.pos anots.no_quality_segments.info{1}];% timing and duration? units? % if strcmpi(anots.no_quality_segments.units,'sec') || strcmpi(anots.no_quality_segments.units,'seconds') % data=messages.setup.wavedet.freq*data; % elseif strcmpi(anots.no_quality_segments.units,'msec') || strcmpi(anots.no_quality_segments.units,'miliseconds') % data=messages.setup.wavedet.freq*data/1000; % else % messages.warnings=[messages.warnings {'no quality segments assumed to be in samples'}]; % end % % for data in samples % indexes=data(data(:,1)>=interval_to_processed(1) & data(:,2)<=interval_to_processed(2),:); % indexes = intervalmatrix(indexes); % indexes(indexes>length(w1))=[]; % else %no quality check % indexes=[]; % end % if ~isempty(indexes) % w1(indexes,1)=0; % swt(indexes,1)=0; % end %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % eps= 0.5*sqrt(nanmean(swt)); eps= rowvec(0.5*sqrt(nanmedian(swt))) .* rowvec(messages.setup.wavedet.QRS_detection_thr); eps(4) = eps(4)*2; %%%%%%% multilead%%% Rute 02.Dec.04 % if size(sig,2)>1 % % lead 2 % if messages.setup.wavedet.filter_bank_design==0;% RUTE 24NOV2011 % wt = wavt5(sig(:,2)',q1,q2,q3,q4,q5); % WT equivalent filtering % 22/05/02 Rute including scale 5 % wt=wt(l5:end,1:5); % Remove "incorrect" samples % %samp = (inisamp + l5 -1):endsamp-d5; % % First l5-1 samples are not correctly filtered (border effect) % % Last d5 samples are discarded in order to alineate all the % % filtered signals, taking into acount the filter delays % % Synchronizing filtered signals at different scales % w2 = zeros(size(wt,1)-d5,5); % w2(:,5) = wt(d5+1:end,5); % w2(:,4) = wt(d4+1:end+d4-d5,4); % w2(:,3) = wt(d3+1:end+d3-d5,3); % w2(:,2) = wt(d2+1:end+d2-d5,2); % w2(:,1) = wt(d1+1:end+d1-d5,1); % else % clear w2 % w2(1:size(wtECG,1),1:5) = wtECG(:,2,:);% RUTE 24NOV2011 % end % swt=w2.^2; % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%check quality of the signal % if messages.setup.wavedet.sig_quality==1 %external % if iscell(aname_sig_quality) && size(aname_sig_quality,2)>1 % aname_sig_quality_cell{2}=aname_sig_quality(:,2); % anots = readannot_mat(dirann_sig_quality,aname_sig_quality_cell{2},'no_quality_segments'); % data = [anots.no_quality_segments.pos anots.no_quality_segments.info{1}];% timing and duration? units? % if strcmpi(anots.no_quality_segments.units,'sec') || strcmpi(anots.no_quality_segments.units,'seconds') % data=messages.setup.wavedet.freq*data; % elseif strcmpi(anots.no_quality_segments.units,'msec') || strcmpi(anots.no_quality_segments.units,'miliseconds') % data=messages.setup.wavedet.freq*data/1000; % else % messages.warnings=[messages.warnings {'no quality segments assumed to be in samples'}]; % end % for data in samples % indexes=data(data(:,1)>=interval_to_processed(1) & data(:,2)<=interval_to_processed(2),:); % indexes = intervalmatrix(indexes); % end % indexes(indexes>length(w2))=[]; % else %no quality check % indexes=[]; % end % if ~isempty(indexes) % w2(indexes,1)=0; % swt(indexes,1)=0; % end % %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % Initialization of the thresholds for QRS detection (eps) % eps(2,:)= 0.5*sqrt(mean(swt)); % eps(2,4) = eps(2,4)*2; % % if size(sig,2)>2 % % lead 3 % if messages.setup.wavedet.filter_bank_design==0;% RUTE 24NOV2011 % wt = wavt5(sig(:,3)',q1,q2,q3,q4,q5); % WT equivalent filtering % 22/05/02 Rute including scale 5 % wt=wt(l5:end,1:5); % Remove "incorrect" samples % %samp = (inisamp + l5 -1):endsamp-d5; % % First l5-1 samples are not correctly filtered (border effect) % % Last d5 samples are discarded in order to alineate all the % % filtered signals, taking into acount the filter delays % % % Synchronizing filtered signals at different scales % w3 = zeros(size(wt,1)-d5,5); % w3(:,5) = wt(d5+1:end,5); % w3(:,4) = wt(d4+1:end+d4-d5,4); % w3(:,3) = wt(d3+1:end+d3-d5,3); % w3(:,2) = wt(d2+1:end+d2-d5,2); % w3(:,1) = wt(d1+1:end+d1-d5,1); % else % clear w3 % w3(1:size(wtECG,1),1:5) = wtECG(:,3,:);% RUTE 24NOV2011 % end % swt=w3.^2; % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%check quality of the signal % if messages.setup.wavedet.sig_quality==1 %external % if iscell(aname_sig_quality) && size(aname_sig_quality,2)>2 % aname_sig_quality_cell{3}=aname_sig_quality(:,3); % anots = readannot_mat(dirann_sig_quality,aname_sig_quality_cell{3},'no_quality_segments'); % data = [anots.no_quality_segments.pos anots.no_quality_segments.info{1}];% timing and duration? units? % if strcmpi(anots.no_quality_segments.units,'sec') || strcmpi(anots.no_quality_segments.units,'seconds') % data=messages.setup.wavedet.freq*data; % elseif strcmpi(anots.no_quality_segments.units,'msec') || strcmpi(anots.no_quality_segments.units,'miliseconds') % data=messages.setup.wavedet.freq*data/1000; % else % messages.warnings=[messages.warnings {'no quality segments assumed to be in samples'}]; % end % % for data in samples % indexes=data(data(:,1)>=interval_to_processed(1) & data(:,2)<=interval_to_processed(2),:); % indexes = intervalmatrix(indexes); % end % indexes(indexes>length(w3))=[]; % else %no quality check % indexes=[]; % end % if ~isempty(indexes) % w3(indexes,1)=0; % swt(indexes,1)=0; % end % %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Initialization of the thresholds for QRS detection (eps) % eps(3,:)= 0.5*sqrt(mean(swt)); % eps(3,4) = eps(3,4)*2; % end % end % sig=sig(l5:end-d5,:); % piece of signal processed in this iteration %messages.lixo=sig; eps=eps'; clear wt swt; %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%% beat detection %%%%%%%%%%%%%%%%%%%%%%%%%%% if qrs_flag==0 || qrs_flag==2 % The QRS fiducial point is calculated with wavedet messages.sig=sig; [position1,timeqrs1,lastqrs1,intervalo1,numlatdet1,time1,messages]= fiducialf(position1,firstnewsamp,samp,heasig,w1,eps,1,lastqrs1,timeqrs1,numlatdet1,ultimo_anot,messages); timeqrs=timeqrs1; % comentar isto pode dar erro no single lead indexes=1:length(timeqrs1); % if size(sig,2)>1 % [position2,timeqrs2,lastqrs2,intervalo2,numlatdet2,time2,messages]= fiducialf(position2,firstnewsamp,samp,heasig,w2,eps,2,lastqrs2,timeqrs2,numlatdet2,ultimo_anot,messages); % if size(sig,2)>2 % [position3,timeqrs3,lastqrs3,intervalo3,numlatdet3,time3,messages]= fiducialf(position3,firstnewsamp,samp,heasig,w3,eps,3,lastqrs3,timeqrs3,numlatdet3,ultimo_anot,messages); % else % timeqrs3=[]; % end % [timeqrs,indexes]=qrscandidatesnew(timeqrs1,timeqrs2,timeqrs3,heasig,messages.setup.wavedet.refrper(end)/2* messages.setup.wavedet.freq); % % %2JUN08 %RUTE no candidates at all do not mark % if ~isempty(timeqrs) % lastqrs1=timeqrs(1,~isnan(timeqrs(1,:))); % if ~isempty(lastqrs1) % lastqrs1=lastqrs1(end); % end % % if sum(~isnan(timeqrs(2,:)))>0 % lastqrs2=timeqrs(2,~isnan(timeqrs(2,:))); % end % if ~isempty(lastqrs2) % lastqrs2=lastqrs2(end); % end % if size(sig,2)>2 % if sum(~isnan(timeqrs(3,:)))>0 % lastqrs3=timeqrs(3,~isnan(timeqrs(3,:))); % end % if ~isempty(lastqrs3) % lastqrs3=lastqrs3(end); % end % end % end % end intervaloall=[intervaloall(end)+1 size(timeqrs,2)]; intervalo=intervaloall; time= timeqrs(:,intervaloall(1):intervaloall(end))-samp(1)+1; if ~isempty(time) && size(sig,2)>1 %16OUT08 position0.qrs(intervalo(1):intervalo(end))=round(nanmedian(time)+samp(1)-1); % 09AGO2011 position.qrs(intervalo(1):intervalo(end))=round(nanmedian(time)+samp(1)-1); % 09AGO2011 end else % The QRS fiducial point is read from external annotator % multilead need to be checked first = max(firstnewsamp-ceil(messages.setup.wavedet.freq), samp(1)-1+ceil( messages.setup.wavedet.freq*0.050)); % first is calculated according with the first lines of fiducial JP sel=find(ext_anot>=first & ext_anot<=samp(end)); % % position1.qrs(sel)=ext_anot(sel); %4ABRIL2011 position1.qrs = rowvec(ext_anot); timeqrs(1,sel)=position1.qrs(sel)-samp(1)+1; %global time=timeqrs(1,sel);%4ABRIL2011 ?????%local indexes= 1:length(timeqrs(1,:));%4ABRIL2011 lastqrs1=timeqrs(1,~isnan(timeqrs(1,:))); if ~isempty(lastqrs1) lastqrs1=lastqrs1(end); end if ~isempty(sel) intervaloall=[sel(1) sel(end)]; % time=[timeqrs(:,intervaloall(1):intervaloall(end))-samp(1)+1]; else intervaloall=[]; %time=[]; end intervalo=intervaloall; intervalo1=intervalo;%4ABRIL2011 time1=time;%4ABRIL2011 if size(sig,2)>1 position2.qrs(sel)=ext_anot(sel);%4ABRIL2011 timeqrs(2,sel)=position2.qrs(sel)-samp(1)+1; time(2,:)= time(1,:);%4ABRIL2011 indexes=[indexes; indexes];%#ok%4ABRIL2011 if sum(~isnan(timeqrs(2,:)))>0 lastqrs2=timeqrs(2,~isnan(timeqrs(2,:))); end if ~isempty(lastqrs2) lastqrs2=lastqrs2(end); end intervalo2=intervalo;%4ABRIL2011 time2=time; if size(sig,2)>2 position3.qrs(sel)=ext_anot(sel);%4ABRIL2011 timeqrs(3,sel)=position3.qrs(sel)-samp(1)+1; time=[time;time(1,:)];%#ok %4ABRIL2011 indexes=[indexes; indexes];%#ok%4ABRIL2011 if sum(~isnan(timeqrs(3,:)))>0 lastqrs3=timeqrs(3,~isnan(timeqrs(3,:))); end if ~isempty(lastqrs3) lastqrs3=lastqrs3(end); end intervalo3=intervalo;%4ABRIL2011 time3=time; else indexes=[indexes;NaN*(1:length(timeqrs(1,:)))];%#ok%9MAYO2011 end end if ~isempty(time) && size(sig,2)>2 %Rute 13Set06 %by default position is the median mark position0.qrs(intervalo(1):intervalo(end))=round(nanmedian(time)+samp(1)-1); % 09AGO2011 position.qrs(intervalo(1):intervalo(end))=round(nanmedian(time)+samp(1)-1); % 09AGO2011 end % If the P-wave is not in the present segment, discard the beat, because the % the beat should have been detected in the last segment. %%%%%%%%%%%%%%%%% Rute 03.Dec.04? % if abs(samp(time(1)) - lastqrs)< 0.275*heasig.spf_ecg*heasig.freq, % time(1)=[]; sel(1)=[]; % In order not to repeat beats % end % if (length(sig)-time(end) < 0.45*heasig.spf_ecg*heasig.freq), % time(end)=[]; sel(end)=[]; % end % If last beat's T-wave is not in 'sig', the beat is detected in next one %%% timeqrs = [timeqrs samp(time)]; % QRS times ??????????????? Rute 03.Dec.04? %lastqrs = samp(time(end));Rute 03.Dec.04? % numeration of the beats processed in this segment end if size(sig,2)>1 timenew=round(nanmedian(time)); %RUTE 09/07/2007 else timenew=time; end if( ~messages.setup.wavedet.QRS_detection_only ) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%% QRS delineation %%%%%%%%%%%%%%%%%%%%%%%%%%% %if ~isempty(time(1,:)) %2JUN08 RUTE if ~isempty(time) %2JUN08 RUTE QRSon=indexes(:,intervalo(1):intervalo(end)); qrspiconsetall=NaN*ones(3,intervalo(end)-intervalo(1)+1); QRSoff=indexes(:,intervalo(1):intervalo(end)); qrspicoffsetall=NaN*ones(3,intervalo(end)-intervalo(1)+1); if ~isempty(intervalo1) [position1,qrspiconset1,qrspicoffset1,messages]= qrswavef(heasig,samp,time1,position1,w1,intervalo1,messages); auxindexes=indexes(1,intervalo(1):intervalo(end)); %NOTE: CHANGED 10.SET.05 qrspiconsetall(1,(~isnan(indexes(1,intervalo(1):intervalo(end)))&(QRSon(1,:)>=intervalo1(1)&QRSon(1,:)<=intervalo1(2))))=qrspiconset1(QRSon(1,~isnan(QRSon(1,:))&(QRSon(1,:)>=intervalo1(1)&QRSon(1,:)<=intervalo1(2)))-intervalo1(1)+1); %17Mar06 QRSon(1,~isnan(QRSon(1,:)))=position1.QRSon(QRSon(1,~isnan(QRSon(1,:)))); qrspicoffsetall(1,(~isnan(indexes(1,intervalo(1):intervalo(end)))&(QRSoff(1,:)>=intervalo1(1)&QRSoff(1,:)<=intervalo1(2))))=qrspicoffset1(QRSoff(1,~isnan(QRSoff(1,:))&(QRSoff(1,:)>=intervalo1(1)&QRSoff(1,:)<=intervalo1(2)))-intervalo1(1)+1); QRSoff(1,~isnan(QRSoff(1,:)))=position1.QRSoff(QRSoff(1,~isnan(QRSoff(1,:)))); end if size(sig,2)>1 [position2,qrspiconset2,qrspicoffset2,messages]= qrswavef(heasig,samp,time2,position2,w2,intervalo2,messages); if ~isempty(intervalo2) auxindexes=indexes(2,intervalo(1):intervalo(end)); qrspiconsetall(2,(~isnan(indexes(2,intervalo(1):intervalo(end)))&(QRSon(2,:)<=intervalo2(2)&QRSon(2,:)>=intervalo2(1))))=qrspiconset2(QRSon(2,~isnan(QRSon(2,:))&(QRSon(2,:)<=intervalo2(2)&QRSon(2,:)>=intervalo2(1)))-intervalo2(1)+1); %Rute 17Mar06 QRSon(2,~isnan(QRSon(2,:)))=position2.QRSon(QRSon(2,~isnan(QRSon(2,:)))); qrspicoffsetall(2,(~isnan(indexes(2,intervalo(1):intervalo(end)))&(QRSoff(2,:)<=intervalo2(2)&QRSoff(2,:)>=intervalo2(1))))=qrspicoffset2(QRSoff(2,~isnan(QRSoff(2,:))&(QRSoff(2,:)<=intervalo2(2)&QRSoff(2,:)>=intervalo2(1)))-intervalo2(1)+1); %Rute 17Mar06 QRSoff(2,~isnan(QRSoff(2,:)))=position2.QRSoff(QRSoff(2,~isnan(QRSoff(2,:)))); end if size(sig,2)>2 && ~isempty(intervalo3) [position3,qrspiconset3,qrspicoffset3,messages]= qrswavef(heasig,samp,time3,position3,w3,intervalo3,messages); %#ok auxindexes=indexes(3,intervalo(1):intervalo(end)); if max(QRSon(3,~isnan(QRSon(3,:))&(QRSon(3,:)>=intervalo3(1)&QRSon(3,:)<=intervalo3(2)))-intervalo3(1)+1)> length(qrspiconset3)%17.Mar.06 qrspiconsetall(3,(QRSon(3,~isnan(QRSon(3,:))&(QRSon(3,:)<=intervalo3(2)&QRSon(3,:)>=intervalo3(1)))-intervalo3(1)+1)<=length(qrspiconsetall(3,(~isnan(indexes(3,intervalo(1):intervalo(end)))&(QRSon(3,:)<=intervalo3(2)&QRSon(3,:)>=intervalo3(1)))))&(~isnan(indexes(3,intervalo(1):intervalo(end)))&(QRSon(3,:)>=intervalo3(1))))=qrspiconset3((QRSon(3,~isnan(QRSon(3,:))&(QRSon(3,:)>=intervalo3(1)))-intervalo3(1)+1)<=length(qrspiconsetall(3,(~isnan(indexes(3,intervalo(1):intervalo(end)))&(QRSon(3,:)>=intervalo3(1)))))& QRSon(3,~isnan(QRSon(3,:))&(QRSon(3,:)>=intervalo3(1)))-intervalo3(1)+1);%17Mar06 else%16.Fev.06 qrspiconsetall(3,(~isnan(indexes(3,intervalo(1):intervalo(end)))&(QRSon(3,:)>=intervalo3(1))))=qrspiconset3(QRSon(3,~isnan(QRSon(3,:))&(QRSon(3,:)>=intervalo3(1)))-intervalo3(1)+1); end %16.Fev.06 QRSon(3,~isnan(QRSon(3,:)))=position3.QRSon(QRSon(3,~isnan(QRSon(3,:)))); if max(QRSoff(3,~isnan(QRSoff(3,:))&(QRSoff(3,:)>=intervalo3(1)&QRSoff(3,:)<=intervalo3(2)))-intervalo3(1)+1)> length(qrspiconset3)%17.Mar.06 qrspicoffsetall(3,(QRSoff(3,~isnan(QRSoff(3,:))&(QRSoff(3,:)<=intervalo3(2)&QRSoff(3,:)>=intervalo3(1)))-intervalo3(1)+1)<=length(qrspicoffsetall(3,(~isnan(indexes(3,intervalo(1):intervalo(end)))&(QRSoff(3,:)<=intervalo3(2)&QRSoff(3,:)>=intervalo3(1)))))&(~isnan(indexes(3,intervalo(1):intervalo(end)))&(QRSoff(3,:)>=intervalo3(1))))=qrspiconset3((QRSoff(3,~isnan(QRSoff(3,:))&(QRSoff(3,:)>=intervalo3(1)))-intervalo3(1)+1)<=length(qrspicoffsetall(3,(~isnan(indexes(3,intervalo(1):intervalo(end)))&(QRSoff(3,:)>=intervalo3(1)))))& QRSoff(3,~isnan(QRSoff(3,:))&(QRSoff(3,:)>=intervalo3(1)))-intervalo3(1)+1);%17Mar06 else%16.Fev.06 qrspicoffsetall(3,(~isnan(indexes(3,intervalo(1):intervalo(end)))&(QRSoff(3,:)>=intervalo3(1))))=qrspiconset3(QRSoff(3,~isnan(QRSoff(3,:))&(QRSoff(3,:)>=intervalo3(1)))-intervalo3(1)+1); end %16.Fev.06 QRSoff(3,~isnan(QRSoff(3,:)))=position3.QRSoff(QRSoff(3,~isnan(QRSoff(3,:)))); end end auxqrspiconset=nanmin(qrspiconsetall); auxqrspicoffset=nanmax(qrspicoffsetall); aux=find(isnan(auxqrspiconset)); auxaux=intervalo(1):intervalo(end); % if ~isempty(aux) % one beat is from the former interval 1.AGO.07 % if aux(1)>1 % messages.errors=[messages.errors {['QRS onset not found at beat(s): ' num2str(auxaux(aux ))]}]; % warning(char(messages.errors(end))); % end auxqrspiconset(aux)=[]; QRSon(:,aux)=[]; %31.07.07 auxqrspicoffset(aux)=[]; QRSoff(:,aux)=[]; %31.07.07 intervalo(end)=intervalo(end)-aux(end); %16MAR09 time(:,aux)=[];%31.07.07 timenew(:,aux)=[];%31.07.07 if length(auxaux)>size(QRSon,2) auxaux(aux)=[]; end end if size(sig,2)>1 %Rute 16Out08 %by default QRS onset in the earliest of the marks %by default QRS end in the latest of the marks position0.QRSon(auxaux)=min(QRSon); position.QRSon(auxaux)=min(QRSon); position0.QRSoff(auxaux)=max(QRSoff); position.QRSoff(auxaux)=max(QRSoff); end if size(sig,2)>1 if ~exist('w3','var') w3=[]; end timeaux=time; %time is sorted %18.07.07 auxaux=NaN*ones(3,intervalo(end)-intervalo(1)+1); auxindexes=indexes(:,intervalo(1):intervalo(end)); auxaux(1,~isnan(indexes(1,intervalo(1):intervalo(end))))=position1.R(auxindexes(1,~isnan(indexes(1,intervalo(1):intervalo(end))))); auxaux(2,~isnan(indexes(2,intervalo(1):intervalo(end))))=position2.R(auxindexes(2,~isnan(indexes(2,intervalo(1):intervalo(end))))); auxaux(3,~isnan(indexes(3,intervalo(1):intervalo(end))))=position3.R(auxindexes(3,~isnan(indexes(3,intervalo(1):intervalo(end))))); position.R(intervalo(1):intervalo(end))=nanmin(auxaux); %timenew is the median, use min instead? [position0,position,messages]=multiqrson(heasig,w1,w2,w3,auxqrspiconset,QRSon,timeaux,timenew,position0,position,intervalo,samp,messages); timeaux=time; position.R(intervalo(1):intervalo(end))=round(nanmedian(auxaux)); %RUTE 09AGO2011 %MEDIAN %by default position is the median mark of all R %timenew is the median, use max instead? [position0,position,messages]=multiqrsend(heasig,w1,w2,w3,auxqrspicoffset,QRSoff,timeaux,timenew,position0,position, intervalo,samp,messages); position.R(intervalo(1):intervalo(end))=round(nanmedian(auxaux));%RUTE 09AGO2011 % squaresignal=(sig(:,1)/max(sig(:,1))).^2+(sig(:,2)/max(sig(:,2))).^2+(sig(:,3)/max(sig(:,3))).^2; % for ii=intervalo(1):intervalo(end) % if ~isempty(position.QRSon(ii):position.QRSoff(ii)) % [M,position.qrsnew(ii)]=max(squaresignal(position.QRSon(ii):position.QRSoff(ii))); % position.qrsnew(ii)=position.qrsnew(ii)+position.QRSon(ii)-1; % end % end end % lastqrs1=timeqrs(1,end); %%%%%%%%%%%%%%%% caso em que rr tem dimensao inferior ao necessario %%%%%%%%%%%%%%%% protection with respect to ultimo_anot while eval(['position' str '.QRSon(intervalo(1))1 && ~isempty(time2) if length(time2(1,:))>1%23SET08 [position2,janelas2,messages]= twavef(heasig,samp,time2,position2,w2,intervalo2,messages);%21AGO09 end if size(sig,2)>2 && ~isempty(intervalo3) if length(time3(1,:))>1%23SET08 [position3,janelas3,messages]= twavef(heasig,samp,time3,position3,w3,intervalo3,messages);%21AGO09 end end end if size(sig,2)>1 subintervalo=indexes(:,intervalo(1):intervalo(end)); %NOTE are excluded the ones from the previous seg if ~isempty(intervalo1) aux1=subintervalo(1,~isnan(subintervalo(1,:)))-intervalo1(1)+1; end if size(sig,2)>1 & ~isempty(intervalo2) %#ok aux2=subintervalo(2,~isnan(subintervalo(2,:)))-intervalo2(1)+1; end if size(sig,2)>2 & ~isempty(intervalo3) %#ok aux3=subintervalo(3,~isnan(subintervalo(3,:)))-intervalo3(1)+1; end %26.04.05 janelas=NaN*ones(size(subintervalo,2),9); janelas(:,1)=(intervalo(1):intervalo(end))'; janelas(:,4)=(intervalo(1):intervalo(end))'; janelas(:,7)=(intervalo(1):intervalo(end))'; if ~isempty(intervalo1) janelas(~isnan(subintervalo(1,:)-intervalo1(1)+1),2)=aux1'; end if ~isempty(intervalo2) janelas(~isnan(subintervalo(2,:)-intervalo2(1)+1),5)=aux2'; end if ~isempty(intervalo1) aux1=aux1(aux1>0); end aux2=aux2(aux2>0); if size(sig,2)>2 & ~isempty(intervalo3) %#ok janelas(~isnan(subintervalo(3,:)-intervalo3(1)+1),8)=aux3'; aux3=aux3(aux3>0); end janelas(janelas<=0)=NaN; if exist('janelas1','var')&& sum(~isnan(janelas(:,2)))~=0 janelas(~isnan(janelas(:,2)) & janelas(:,2)>0,2:3)=janelas1(aux1,2:3); end if exist('janelas2','var')& ~isempty(janelas(~isnan(janelas(:,5)) & janelas(:,5)>0 ,5:6)) %#ok if max(aux2) > length(janelas2)%17.Mar.06 janelas(~isnan(janelas(:,5)) & janelas(:,5)>0 ,5:6)=[janelas2((aux2) <= length(janelas2),2:3); NaN*ones(sum(aux2 > length(janelas2)),2)];%14.Mar.06 else%16.Fev.06 janelas(~isnan(janelas(:,5)) & janelas(:,5)>0 ,5:6)=janelas2(aux2,2:3); end%16.Fev.06 end if size(sig,2)>2 & ~isempty(intervalo3) %#ok %ver altera�ao por erro de indexes em irec5 de %politec!!!!%16.Fev.06 if exist('janelas3','var') if max(aux3) > length(janelas3)%16.Fev.06 %janelas(~isnan(janelas(:,8)) & janelas(:,8)>0 ,8:9)=[janelas3(aux3(1:(end-1)),2:3);NaN NaN];%16.Fev.06 janelas(~isnan(janelas(:,8)) & janelas(:,8)>0 ,8:9)=[janelas3((aux3) <= length(janelas3),2:3); NaN*ones(sum(aux3 > length(janelas3)),2)];%14.Mar.06 else%16.Fev.06 janelas(~isnan(janelas(:,8)) & janelas(:,8)>0 ,8:9)=janelas3(aux3,2:3); end%16.Fev.06 end end %cases were begwin>endwin!!! janelas((janelas(:,3))<=janelas(:,2)|isnan(janelas(:,3)),2)=NaN; janelas(janelas(:,3)<=janelas(:,2)|isnan(janelas(:,2)),3)=NaN; janelas(janelas(:,6)<=janelas(:,5)|isnan(janelas(:,6)),5)=NaN; janelas(janelas(:,6)<=janelas(:,5)|isnan(janelas(:,5)),6)=NaN; janelas(janelas(:,9)<=janelas(:,8)|isnan(janelas(:,9)),8)=NaN; janelas(janelas(:,9)<=janelas(:,8)|isnan(janelas(:,8)),9)=NaN; begwin= min(janelas(:,[2 5 8])'); %#ok endwin= max(janelas(:,[3 6 9])'); %#ok intreg=[begwin' endwin']; count=count+1; if ~exist('w3','var') w3=[]; end [position0,position,messages]= delineate3D(w1,w2,w3,intreg,timenew,position0,position,intervalo,position1,position2,position3,indexes,samp,[],messages); % 05MAY2011 end %end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24AGO2011 if ~exist('str','var'), str=''; end eval(['position' str '.QRSon(position' str '.R<=(position' str '.QRSon+1))=NaN;']); eval(['position' str '.QRSoff(position' str '.QRSoff>=(position' str '.Ton-1))=NaN;']); eval(['position' str '.QRSoff(position' str '.QRSoff>=(position' str '.T-1))=NaN;']); eval(['position' str '.QRSoff(position' str '.QRSoff<=(position' str '.qrs+1))=NaN;']); eval(['position' str '.QRSoff(position' str '.R>=(position' str '.QRSoff-1))=NaN;']); eval(['position' str '.Toff(position' str '.Toff<=(position' str '.T+1))=NaN;']); eval(['position' str '.Ton(position' str '.Ton>=(position' str '.T-1))=NaN;']); eval(['ii=1:sum(position' str '.qrs>0);']); eval(['position' str '.QRSoff(position' str '.QRSoff(ii(1:end-1))>=(position' str '.R(ii(2:end))))=NaN;']); eval(['position' str '.QRSoff(position' str '.QRSoff(ii(1:end-1))>=(position' str '.qrs(ii(2:end))))=NaN;']); eval(['position' str '.Toff(position' str '.Toff(ii(1:end-1))>=position' str '.qrs(ii(2:end)))=NaN;']); %%%%%%%%%%%%%%%%%%%%%%%%%%%% P wave %%%%%%%%%%%%%%%%%%%%%%%%%%% %11.04.05 P wave delineation inside the condition of existing some [position1,picon_all,picoff_all,messages]= pwavef(heasig,samp,time1,position1,w1,intervalo1,ultimo_anot,messages); %#ok if size(sig,2)>1 [position2,picon_all,picoff_all,messages]= pwavef(heasig,samp,time2,position2,w2,intervalo2,ultimo_anot,messages); %#ok if size(sig,2)>2 & ~isempty(intervalo3) %#ok [position3,picon_all,picoff_all,messages]= pwavef(heasig,samp,time3,position3,w3,intervalo3,ultimo_anot,messages); %#ok auxaux(1,~isnan(indexes(1,intervalo(1):intervalo(end))))=position1.P(auxindexes(1,~isnan(indexes(1,intervalo(1):intervalo(end))))); auxaux(2,~isnan(indexes(2,intervalo(1):intervalo(end))))=position2.P(auxindexes(2,~isnan(indexes(2,intervalo(1):intervalo(end))))); auxaux(3,~isnan(indexes(3,intervalo(1):intervalo(end))))=position3.P(auxindexes(3,~isnan(indexes(3,intervalo(1):intervalo(end))))); position0.P(intervalo(1):intervalo(end))=round(nanmedian(auxaux)); %RUTE 09AGO2011; %MEDIAN %by default position is the median mark of all R [position0,position,messages]= delineateP3D(heasig,w1,w2,w3,timenew,position0,position,intervalo,samp,ultimo_anot,messages); end end %check the position structure size eval(['position' str '.Pon((length(position' str '.Pon)+1):length(position' str '.qrs))=NaN;']); %6May2011 eval(['position' str '.P((length(position' str '.P)+1):length(position' str '.qrs))=NaN;']); %6May2011 eval(['position' str '.Poff((length(position' str '.Poff)+1):length(position' str '.qrs))=NaN;']); %6May2011 eval(['position' str '.Poff((length(position' str '.Poff)+1):length(position' str '.qrs))=NaN;']); %6May2011 if size(sig,2)>2 %6May2011 position0.Pon((length(position0.Pon)+1):length(position.qrs))=NaN; position0.P((length(position0.P)+1):length(position.qrs))=NaN; position0.Poff((length(position0.Poff)+1):length(position.qrs))=NaN; end end %%%%%%%%%%%%%%%%%%%%%%%%%%%% finishing excerpt %%%%%%%%%%%%%%%%%%%%%%%%%%% % Last annotated position if intervalo(2)>0 if size(sig,2)>1 if ~isnan(position.Toff(min(intervalo(2),length(position.Toff)))), ultimo_anot = position.Toff(min(intervalo(2),length(position.Toff))); ultimo_anottyp=10; elseif ~isnan(position.Tprima(min(intervalo(2),length(position.Tprima)))), ultimo_anot = position.Tprima(min(intervalo(2),length(position.Tprima))); ultimo_anottyp=9; elseif ~isnan(position.T(min(intervalo(2),length(position.T)))), ultimo_anot = position.T(min(intervalo(2),length(position.T))); ultimo_anottyp=8; elseif ~isnan(position.QRSoff(min(intervalo(2),length(position.QRSoff)))), ultimo_anot = position.QRSoff(min(intervalo(2),length(position.QRSoff))); ultimo_anottyp=6; else ultimo_anot = ceil(position.qrs(min(intervalo(2),length(position.qrs)))); ultimo_anottyp=5; end else if ~isnan(position1.Toff(min(intervalo(2),length(position1.Toff)))), ultimo_anot = position1.Toff(min(intervalo(2),length(position1.Toff))); ultimo_anottyp=10; elseif ~isnan(position1.Tprima(min(intervalo(2),length(position1.Tprima)))), ultimo_anot = position1.Tprima(min(intervalo(2),length(position1.Tprima))); ultimo_anottyp=9; elseif ~isnan(position1.T(min(intervalo(2),length(position1.T)))), ultimo_anot = position1.T(min(intervalo(2),length(position1.T))); ultimo_anottyp=8; elseif ~isnan(position1.QRSoff(min(intervalo(2),length(position1.QRSoff)))), ultimo_anot = position1.QRSoff(min(intervalo(2),length(position1.QRSoff))); ultimo_anottyp=6; else ultimo_anot = ceil(position1.qrs(min(intervalo(2),length(position1.qrs)))); ultimo_anottyp=5; end end end end %%%%%%%%%%%%%%%%introduzido a 17/05/02 Rute end inisamp = endsamp +2-endoverlap-begoverlap; end if( ~messages.setup.wavedet.QRS_detection_only ) eval(['position' str '.Pon((length(position' str '.Pon)+1):length(position' str '.qrs))=NaN;']); eval(['position' str '.P((length(position' str '.P)+1):length(position' str '.qrs))=NaN;']); eval(['position' str '.Pprima((length(position' str '.Pprima)+1):length(position' str '.qrs))=NaN;']); eval(['position' str '.Poff((length(position' str '.Poff)+1):length(position' str '.qrs))=NaN;']); eval(['position' str '.Ton((length(position' str '.Ton)+1):length(position' str '.qrs))=NaN;']); eval(['position' str '.T((length(position' str '.T)+1):length(position' str '.qrs))=NaN;']); eval(['position' str '.Tprima((length(position' str '.Tprima)+1):length(position' str '.qrs))=NaN;']); eval(['position' str '.Toff((length(position' str '.Toff)+1):length(position' str '.qrs))=NaN;']); eval(['position' str '.Ttipo((length(position' str '.Ttipo)+1):length(position' str '.qrs))=NaN;']); eval(['position' str '.Tscale((length(position' str '.Tscale)+1):length(position' str '.qrs))=NaN;']); eval(['position' str '.Pon(position' str '.Pon>=(position' str '.qrs))=NaN;']); eval(['position' str '.P(position' str '.P>=(position' str '.qrs))=NaN;']); eval(['position' str '.Pprima(position' str '.Pprima>=(position' str '.qrs))=NaN;']); eval(['position' str '.Poff(position' str '.Poff>=(position' str '.qrs))=NaN;']); eval(['position' str '.Pon(position' str '.Pon>=(position' str '.QRSon))=NaN;']); eval(['position' str '.P(position' str '.P>=(position' str '.QRSon))=NaN;']); eval(['position' str '.Pprima(position' str '.Pprima>=(position' str '.QRSon))=NaN;']); eval(['position' str '.Poff(position' str '.Poff>=(position' str '.QRSon))=NaN;']); eval(['position' str '.Pon(position' str '.Pon>=(position' str '.P))=NaN;']); eval(['position' str '.Poff(position' str '.Poff<=(position' str '.P))=NaN;']); eval(['position' str '.Ton(position' str '.Ton>=(position' str '.T))=NaN;']); eval(['position' str '.Toff(position' str '.Toff<=(position' str '.T))=NaN;']); end %%%%%%%%%%%%%%%%%%%%%%%%%%%% position assigment %%%%%%%%%%%%% % Remove void annotations at the end %strf = {'Pon';'P';'Pprima';'Ptipo';'Poff';'QRSon';'Q';'R';'qrs';'Rprima';'S';'QRSoff';... % 'QRSpa';'QRSpp';'Ton';'T';'Tprima';'Toff';'Ttipo';'Tscale';'QRSmainpos';'QRSmaininv'}; strf = []; for i = 1:3 eval(['strf =fieldnames(position' num2str(i) ');']); % RUTE 4 AGO2011 eval(['aux = find(position' num2str(i) '.qrs == 0| isnan(position' num2str(i) '.qrs));']); for j = 1:length(strf) eval(['aux_l=aux(aux<=size(position' num2str(i) '.' strf{j} ',2));']) eval(['position' num2str(i) '.' strf{j} '(aux_l) = [];']); end end if size(lead,2)==1 position=position1; % 28FEB2012 if ~isempty(position.QRSmainpos) && ~isempty(position.QRSmaininv) a = length(find(position.QRSmainpos == position.qrs)); b = length(find(position.QRSmaininv == position.qrs)); if a >= b position.qrs_hrv = '+'; else position.qrs_hrv = '-'; end end else % strf = {'Pon';'P';'Poff';'QRSon';'Q';'R';'qrs';'Rprima';'S';'QRSoff';... % 'Ton';'T';'Tprima';'Toff';'Ttipo';'Tscale'}; % strf2 = {'Ttipoon';'Ttipooff'}; % strf3 = {'QRSonsetcriteria';'QRSoffcriteria';'contadorToff';... % 'R_inQRSon';'R_inQRSoff'}; strn = {'0';''}; for i = 1:2 strM = 'MM = max(['; eval(['aux = find(position' strn{i} '.qrs == 0 | isnan(position' strn{i} '.qrs));']); eval(['strf =fieldnames(position' strn{i} ');']); % RUTE 4 AGO2011 strd = ','; for j = 1:length(strf) eval(['aux_l=aux(aux<=size(position' strn{i} '.' strf{j} ',2));']) eval(['position' strn{i} '.' strf{j} '(aux_l) = [];']); if j == length(strf) strd = ']);'; end strM = [strM 'size(position' strn{i} '.' strf{j} ')' strd]; %#ok end eval(strM); for j = 1:length(strf) eval(['position' strn{i} '.' strf{j} '(:,end+1:MM)=NaN*ones(size(position' strn{i} '.' strf{j} ',1),MM-size(position' strn{i} '.' strf{j} ',2));']) end end end % try % annstruct = pos2ann(position); % if ~isempty(annstruct.time) % writeannot([matdir ecgnr '.' anot], annstruct); % mexfile, faster! % end % catch me % me.message = 'No MIT format annotation file saved.'; % messages.warnings=[messages.warnings {me.message}]; % end for j = 1:4 eval(['positionaux.position' num2str(j-1) ' = position' num2str(j-1) ';']); % RUTE 09.07.2007 end % clear global OPT ecgnr if exist('fid','var') && fid > 2 fclose(fid); % JBOLEA 11MAY2010 end