function [position,timeqrs,lastqrs,intervalo,numlatdet,time,messages]= fiducialf(position,firstnewsamp,samp,heasig,w,eps,nlead,lastqrs,timeqrs,numlatdet,ultimo_anot,messages) % [position,timeqrs,lastqrs,intervalo,numlatdet,time,messages]= fiducialf(position,firstnewsamp,samp,heasig,w,eps,nlead,lastqrs,timeqrs,numlatdet,messages) % % This script performs the QRS fiducial point detection of ECG % In this version the thresholds eps(x) are not beat to beat actualized. % %Input Parameters: % position: struct vector with the detected points % firstnewsamp: last sample analyzed in the previous excerpt % samp: samples included in the current excerpt (borders excluded) % heasig: struct vector with header information % w: matrix with WT scales 1 to 5 % eps: thresholds % nlead: lead to be delineated % lastqrs: last detecter QRS time (shoud be timeqrs(end)) % timeqrs: QRS times % numlatdet: Number of detected beats until now % ultimo_anot: last annotation in the previous segment %Output Parameters: % intervalo: numeration of the beats processed in this segment % time: beats processed in this segment % Actualized parameters: position,timeqrs,lastqrs,numlatdet,timeqrs % % Last update: Rute Almeida 07FEB2012 % % Designed for MATLAB Version R12; tested with MATLAB Version R13 if nargin<12 || ~isfield(messages.setup,'wavedet') messages.setup.wavedet=[]; end if isfield(messages.setup.wavedet,'auxff') && messages.setup.wavedet.auxff==1 ff=1; if isfield(messages.setup.wavedet,'aux_aa') aa=messages.setup.wavedet.aux_aa; else aa=[1 1500]; end else ff=0; end if isempty(heasig) end if ff==1 figure plot(w(:,1),'k') fig1=gca; set(gca,'xlim',aa) hold on ylabel('W_{2^1}') figure plot(messages.sig,'k') fig2=gca; hold on set(gca,'xlim',aa) ylabel('ECG') figure plot(w(:,3),'k') fig3=gca; set(gca,'xlim',aa) hold on ylabel('W_{2^3}') figure subplot(4,1,1) plot(w(:,4),'k') ylabel('W_{2^4}') hold on figWT4=gca; set(gca,'xlim',aa) subplot(4,1,2) plot(w(:,3),'k') ylabel('W_{2^3}') hold on figWT3=gca; set(gca,'xlim',aa) subplot(4,1,3) plot(w(:,2),'k') hold on ylabel('W_{2^2}') figWT2=gca; set(gca,'xlim',aa) subplot(4,1,4) plot(w(:,1),'k') hold on ylabel('W_{2^1}') figWT1=gca; set(gca,'xlim',aa) figure subplot(4,1,1) plot(messages.sig,'k') ylabel('ECG') hold on % figECG=gca; set(gca,'xlim',aa) subplot(4,1,2) plot(w(:,3),'k') ylabel('W_{2^3}') hold on figECGWT3=gca; set(gca,'xlim',aa) subplot(4,1,3) plot(w(:,2),'k') hold on ylabel('W_{2^2}') figECGWT2=gca; set(gca,'xlim',aa) subplot(4,1,4) plot(w(:,1),'k') hold on ylabel('W_{2^1}') figECGWT1=gca; set(gca,'xlim',aa) end if~isfield(messages.setup.wavedet,'firstmin') messages.setup.wavedet.firstmin=0.050; % minimum time in sec to discart at the beggining end if ~isfield(messages.setup.wavedet,'nghbhd') messages.setup.wavedet.nghbhd=0.025; % neighbourwood for maximum across scales in sec end if ~isfield(messages.setup.wavedet,'peakcriteria') messages.setup.wavedet.peakcriteria=1.2; % If a modulus is more than peakcriteria times greater than others in the sane scale the greatest is chosen end if ~isfield(messages.setup.wavedet,'thmax') messages.setup.wavedet.thmax=5+log(5); %maximum value for log(abs(W_3)) in a maximun line end if ~isfield(messages.setup.wavedet,'th_schb') messages.setup.wavedet.th_schb=5+log(5); %maximum value for log(abs(W_3)) in a maximun line end if ~isfield(messages.setup.wavedet,'thfraction') messages.setup.wavedet.thfraction=0.5; % tolerance below the average log(abs(W_3)) in a maximun line end if ~isfield(messages.setup.wavedet,'intvlthr2') messages.setup.wavedet.intvlthr2=0.15;%threshold interval to consider isolated maximum lines end if ~isfield(messages.setup.wavedet,'intvlthr1') messages.setup.wavedet.intvlthr1=0.12;%threshold interval for considering redundancy end if ~isfield(messages.setup.wavedet,'intvlthr1_2') messages.setup.wavedet.intvlthr1_2=1.5;%reduction on threshold interval for considering redundancy if it subsists end if ~isfield(messages.setup.wavedet,'pictime') messages.setup.wavedet.pictime=0.1;%length of the search window for associated maximumlines in extra verification step end if ~isfield(messages.setup.wavedet,'timelapthr') messages.setup.wavedet.timelapthr=0.125;% maximum interval between two assiciated maximumlines in sec end if ~isfield(messages.setup.wavedet,'refrper') messages.setup.wavedet.refrper=0.275;% Refractary period after a QRS detection in sec end if ~isfield(messages.setup.wavedet,'refrper_reduc')% 22NOV2011 messages.setup.wavedet.refrper_reduc=0;% 22NOV2011 end if ~isfield(messages.setup.wavedet,'rrmaxmaxlim') messages.setup.wavedet.rrmaxmaxlim=0.3; % search back criteria: searchback if RR>wavedet.rrmaxmaxlim sec end if ~isfield(messages.setup.wavedet,'rrmaxlim') messages.setup.wavedet.rrmaxlim=1.5;% search back criteria: searchback if RR>wavedet.rrmaxlim * median(RR) end if ~isfield(messages.setup.wavedet,'rrmaxlimsec') messages.setup.wavedet.rrmaxlimsec=1.5;% search back criteria: searchback if RR>wavedet.rrmaxlimsec end if ~isfield(messages.setup.wavedet,'rrmax_rbt') messages.setup.wavedet.rrmax_rbt=0.1; % search back criteria only if >wavedet.rrmax_rbt sec o end if ~isfield(messages.setup.wavedet,'gapthrs') messages.setup.wavedet.gapthrs=2; % fraction of mean(rr) to decide if there are a final "gap" end if ~isfield(messages.setup.wavedet,'pwaveout') messages.setup.wavedet.pwaveout=0.2;% mimimum time in sec before each beat in order to ensure a complete beat end if ~isfield(messages.setup.wavedet,'twaveout') messages.setup.wavedet.twaveout=0.45; % mimimum time in sec after each beat in order to ensure a complete beat end if ~isfield(messages.setup.wavedet,'refrperdef') messages.setup.wavedet.refrperdef=messages.setup.wavedet.refrper;% end if messages.setup.wavedet.refrper_reduc>=1 % 22NOV2011 messages.setup.wavedet.refrper_reduc=0.9;% 22NOV2011 end refrper=messages.setup.wavedet.refrper(end); peakcriteria=messages.setup.wavedet.peakcriteria; %global regularity intervalo=[]; first = firstnewsamp-round(samp(1))+1; first = max(ceil(messages.setup.wavedet.freq*messages.setup.wavedet.firstmin), first - ceil(1*messages.setup.wavedet.freq)); n = modmax(w(:,4),first,eps(4,nlead),0); % Maximum moduli at scale 4 % Rute 02.Dec.04 if ~isempty(n), signo = sign(w(n,4))'; % Maximum or minimum? neighb = ceil(messages.setup.wavedet.freq*messages.setup.wavedet.nghbhd); % Definition of neighborhood 25 ms. %it makes sence to verify if all m(4,:) diffre at least neighb.... m = zeros(4,length(n)); m(4,:) = n'; % Positions of maximum moduli for k = 1:size(m,2), % For each maximum at scale 4 n3 = modmax(w(max(1,n(k)-neighb):min(n(k)+neighb,size(w,1)),3),2,eps(3,nlead),signo(k));% Rute 02.Dec.04 n3 =n(k)-neighb-1+n3; % Check the neighborhood at scale 3 num = length(n3); if num>0, if num==1, % If only one neighbour maximum m(3,k)= n3; % at scale 3 elseif num>1 % If more than one if ~isempty(find(max(abs(w(n3,3))./(abs(w(n3,3))) % the greatest is chosen m(3,k)= n3(ind); else % Choose the one with minimum distance [aux1,ind]=min(abs(m(4,k)-n3)); %#ok m(3,k)= n3(ind); end end end end ind = find(m(3,:)==0); % Discard all maximum lines with no if ff==1 axes(figWT4); plot(figWT4,m(4,:),w(m(4,:),4),'ob') plot(figWT4,[aa(1) aa(2)],[eps(4,nlead) eps(4,nlead)],':b') plot(figWT4,[aa(1) aa(2)],-[eps(4,nlead) eps(4,nlead)],':b') if ~isempty(ind) plot(figWT4,m(4,ind),w(m(4,ind),4),'xr') plot(figWT4,[m(4,ind(1))-neighb m(4,ind(1))-neighb],[-5000 5000],':r') plot(figWT4,[m(4,ind(1))+neighb m(4,ind(1))+neighb],[-5000 5000],':r') axes(figWT3); plot(figWT3,[m(4,ind(1))-neighb m(4,ind(1))-neighb],[-5000 5000],':r') plot(figWT3,[m(4,ind(1))+neighb m(3,ind(1))+neighb],[-5000 5000],':r') end plot(figWT3,m(3,m(3,:)~=0),w(m(3,m(3,:)~=0),3),'ob') plot(figWT3,[aa(1) aa(2)],[eps(3,nlead) eps(3,nlead)],':b') plot(figWT3,[aa(1) aa(2)],-[eps(3,nlead) eps(3,nlead)],':b') end m(:,ind) = []; % associated maximum at scale 3 signo(ind)= []; % Search for maximum modula in the neighborhood at scale 2 for k = 1:size(m,2), n2 =modmax(w(max(1,m(3,k)-neighb):min(m(3,k)+neighb,size(w,1)),2),2,eps(2,nlead),signo(k));% Rute 02.Dec.04 n2 =m(3,k)-neighb-1+n2; num = length(n2); if num>0, if num==1, % If only one neighbour maximum m(2,k)= n2; % at scale 2 elseif num>1 % If more than one if ~isempty(find(max(abs(w(n2,2))./(abs(w(n2,2))) % greatest modulus m(2,k)= n2(ind); else % shortest distance [aux1,ind]=min(abs(m(3,k)-n2)); %#ok m(2,k)= n2(ind); end end end end ind = find(m(2,:)==0); % Discard all maximum lines with no if ff==1 % axes(figWT3); if ~isempty(ind) plot(figWT3,[m(3,ind(1))-neighb m(3,ind(1))-neighb],[-5000 5000],':r') plot(figWT3,[m(3,ind(1))+neighb m(3,ind(1))+neighb],[-5000 5000],':r') plot(figWT3,m(3,ind),w(m(3,ind),3),'xr') axes(figWT2); plot(figWT2,[m(3,ind(1))-neighb m(3,ind(1))-neighb],[-5000 5000],':r') plot(figWT2,[m(3,ind(1))+neighb m(3,ind(1))+neighb],[-5000 5000],':r') end plot(figWT2,m(2,m(2,:)~=0),w(m(2,m(2,:)~=0),2),'ob') plot(figWT2,[aa(1) aa(2)],[eps(2,nlead) eps(2,nlead)],':b') plot(figWT2,[aa(1) aa(2)],-[eps(2,nlead) eps(2,nlead)],':b') end m(:,ind) = []; % associated maximum at scale 2 signo(ind)=[]; for k = 1:size(m,2), n1 = modmax(w(max(1,m(2,k)-neighb):min(m(2,k)+neighb,size(w,1)),1),2,eps(1,nlead),signo(k)); % Rute 02.Dec.04 n1 =m(2,k)-neighb-1+n1; n1 = n1(n1 > 0 & n1 <= size(w,1) ); num = length(n1); if num>0, if num==1, % If only one neighbour maximum m(1,k)= n1; % at scale 1 elseif num>1 % If more than one if ~isempty(find(max(abs(w(n1,1))./(abs(w(n1,1))) % greatest modulus m(1,k)= n1(ind); else % shortest distance [aux1,ind]=min(abs(m(2,k)-n1)); %#ok m(1,k)= n1(ind); end end end end ind = find(m(1,:)==0); %Discard all maximum lines with no if ff==1 % axes(figWT2); if ~isempty(ind) plot(figWT2,m(2,ind),w(m(2,ind),2),'xr') end plot(figWT1,m(1,m(1,:)~=0),w(m(1,m(1,:)~=0),1),'ob') plot(figWT1,[aa(1) aa(2)],[eps(1,nlead) eps(1,nlead)],':b') plot(figWT1,[aa(1) aa(2)],-[eps(1,nlead) eps(1,nlead)],':b') end m(:,ind) = []; % associated maximum at scale 1 signo(ind)=[]; %%% Regularity Exponent Validation %%%%%%%%% % alpha is proportional to log(a3(nk3))-log(a1(nk1)) alpha = log(abs(w(m(3,:),3))); % !!!! % alphalinha = log(abs(w(m(3,:),3))) - log (abs(w(m(1,:),1))); % !!! (1) % cometario na versao original%%%%%% Rute 24/04/02 % % %%%% SO % alpha1 = log(abs(w(m(2,:),2))./abs(w(m(1,:),1))); % alpha2 = log(abs(w(m(3,:),3))./abs(w(m(2,:),2))); % alpha3 = log(abs(w(m(4,:),4))./abs(w(m(3,:),3))); % %%%% SO: you are right alpha=alpha1+alpha2 is calculated acording to (1) % %%%% SO: por ahorro computacional se puede eliminar el log, y en el % %%%% SO: valor del threshold si queremos. % % th was not being using at all in many cases, because thmax < min(alpha) % th=min(messages.setup.wavedet.thmax,mean(alpha)-messages.setup.wavedet.thfraction); th=mean(alpha)-messages.setup.wavedet.thfraction; % thlinha=min(5+log(5),mean(alphalinha)-.5); %%%%%% Rute 24/04/02 ind = find(alpha<=th); % always empty?????!????1 % ind=find(alpha3>=1 || alpha1<=0.9 || alpha2<=0.9);% elimination of large T waves if ff==1 plot(fig1,m(1,:),w(m(1,:)),'ob') legend(fig1,{'WT_1','mm lines'},'Location','NorthEastOutside') plot(m(1,ind),w(m(1,ind)),'xr') if ~isempty(ind) ll={'mm lines','rejected mm lines'}; else ll={'mm lines'}; end plot(figECGWT1,m(1,:),w(m(1,:),1),'ob') plot(figECGWT1,m(1,ind),w(m(1,ind),1),'xr') plot(figECGWT2,m(2,:),w(m(2,:),2),'ob') plot(figECGWT2,m(2,ind),w(m(2,ind),2),'xr') plot(figECGWT3,m(3,:),w(m(3,:),3),'ob') plot(figECGWT3,m(3,ind),w(m(3,ind),3),'xr') plot(fig3,m(3,:),w(m(3,:),3),'ob') legend(fig3,{'WT_3','mm lines'},'Location','NorthEastOutside') plot(m(3,ind),w(m(3,ind),3),'xr') % axes(fig1); legend(fig1,['WT_1',ll],'Location','NorthEastOutside') % axes(fig3); legend(fig3,['WT_3',ll],'Location','NorthEastOutside') figure; hs = subplot(3,1,1); plot(hs,w(:,3),'k') ylabel(hs,'W_{2^3}') hold on plot(hs,m(3,:),w(m(3,:),3),'ob') plot(hs,m(3,ind),w(m(3,ind),3),'xr') set(hs,'xlim',aa) hs3 = subplot(3,1,3); plot(hs3,messages.sig,'k') hold on set(hs3,'xlim',aa) ylabel(hs3,'ECG') set(hs3,'xlim',aa) hs2 = subplot(3,1,2); plot(hs2,m(3,:),alpha,'k') hold on plot(hs2,m(3,:),alpha,'ob') plot(hs2,[0 261770],[mean(alpha)-messages.setup.wavedet.thfraction mean(alpha)-messages.setup.wavedet.thfraction],':g') plot(hs2,[0 261770],[th th],':r'), plot(hs2,m(3,ind),alpha(ind),'xr') set(hs2,'xlim',aa) ylabel(hs2,'\alpha') %legend('alpha','alpha','mean alpha-thfraction','th','Location','NorthEastOutside') end if ~isempty(ind) % and high frequency noise peaks m(:,ind) = []; signo(ind)=[]; end thresinterval = ceil(messages.setup.wavedet.intvlthr2* messages.setup.wavedet.freq); % threshold interval to consider isolated maximum lines ind = find( ((m(1,2:end-1)-m(1,1:end-2))>thresinterval) ... & (m(1,3:end)- m(1,2:end-1))>thresinterval)+1; if size(m,2)<2 && ~isempty(ind), ind=1; end % when only one maximum %16DEZ08 if ff==1 % axes(fig1); plot(fig1,m(1,ind),w(m(1,ind)),'+r') if ~isempty(ind) ll=[ll {'isolated mm lines'}]; end % axes(fig1); legend(fig1,['WT_1',ll],'Location','NorthEastOutside') % axes(fig3); plot(fig3,m(3,ind),w(m(3,ind),3),'+r') legend(['WT_3',ll],'Location','NorthEastOutside') try % axes(figECGWT1); plot(figECGWT1,m(1,ind),w(m(1,ind),1),'+r') plot(figECGWT1,[m(1,ind(1))-thresinterval m(1,ind(1))-thresinterval],[-5000 5000],':r') plot(figECGWT1,[m(1,ind(1))+thresinterval m(1,ind(1))+thresinterval],[-5000 5000],':r') % axes(figECGWT2); plot(figECGWT2,m(2,ind),w(m(2,ind),2),'+r') % axes(figECGWT3); plot(figECGWT3,m(3,ind),w(m(3,ind),3),'+r') catch me me.message = 'Error plotting WT signal'; end end m(:,ind) = []; %Discard isolated maximum lines signo(ind)=[]; % Threshold interval for considering redundancy redundant= []; thresinterval = ceil(messages.setup.wavedet.intvlthr1*messages.setup.wavedet.freq); % 120 ms. (li) for l = find(signo>0), % For each positive maximum line if ~any(redundant ==l), % If it has not been declared redundant yet ind=find((m(3,:)>m(3,l)-messages.setup.wavedet.intvlthr1_2*thresinterval)&(m(3,:)0); % index of positive lines near the present one (including it) if length(ind)>1, % If more than one --> redundancy [mx,ind2]= max(abs(w(m(3,ind),3))); %#ok ind(ind2)=[]; redundant = [redundant ind]; %#ok % All but the greatest are redundant end end end if ff==1 % axes(fig1); plot(fig1,m(1,redundant),w(m(1,redundant)),'sm') % axes(fig3); plot(fig3,m(3,redundant),w(m(3,redundant),3),'sm') if ~isempty(redundant) ll=[ll {'redundant mm lines'}]; end % axes(figECGWT1); plot(figECGWT1,m(1,redundant),w(m(1,redundant)),'sm') % axes(figECGWT2); plot(figECGWT2,m(2,redundant),w(m(2,redundant),2),'sm') % axes(figECGWT3); plot(figECGWT3,m(3,redundant),w(m(3,redundant),3),'sm') plot(figECGWT3,[m(3,206)-messages.setup.wavedet.intvlthr1_2*thresinterval m(3,206)-messages.setup.wavedet.intvlthr1_2*thresinterval],[-5000 5000],':r') plot(figECGWT3,[m(3,206)+messages.setup.wavedet.intvlthr1_2*thresinterval m(3,206)+messages.setup.wavedet.intvlthr1_2*thresinterval],[-5000 5000],':r') end m(:,redundant)=[]; % Discard redundant lines signo(redundant)=[]; redundant =[]; for l = find(signo>0), % For each remaining positive maximum line ind=find((m(3,:)>m(3,l)-thresinterval)&(m(3,:)1, % If more than one ---> redundancy aux = abs(w(m(3,ind),3)./(m(3,ind)'-m(3,l))); % auxiliary variable: height over distance [mx,indmx]=max(aux); ind2=ind; aux(indmx)=[]; ind2(indmx)=[]; if all((mx./aux)>peakcriteria), % RULE 2 (see PFC or Li's paper) redundant = [redundant ind2]; %#ok else [aux,aux2]=min(abs(m(3,l)-m(3,ind))); %#ok ind(aux2)=[]; % RULE 1 (see PFC or Li's paper) redundant = [redundant ind]; %#ok end end end if ff==1 % axes(fig1); plot(fig1,m(1,redundant),w(m(1,redundant)),'*r') % axes(fig3); plot(fig3,m(3,redundant),w(m(3,redundant),3),'*r') if ~isempty(redundant) ll=[ll {'redundant mm lines'}]; end try % axes(figECGWT1); plot(figECGWT1,m(1,redundant(end)),w(m(1,redundant(end))),'sm') % axes(figECGWT2); plot(figECGWT2,m(2,redundant(end)),w(m(2,redundant(end)),2),'sm') % axes(figECGWT3); plot(figECGWT3,m(3,redundant(end)),w(m(3,redundant),3),'sm') plot(figECGWT3,[m(3,182)-messages.setup.wavedet.intvlthr1_2*thresinterval m(3,182)-messages.setup.wavedet.intvlthr1_2*thresinterval],[-5000 5000],':r') plot(figECGWT3,[m(3,182)+messages.setup.wavedet.intvlthr1_2*thresinterval m(3,182)+messages.setup.wavedet.intvlthr1_2*thresinterval],[-5000 5000],':r') catch me me.message = 'Error plotting WT signal'; end end m(:,redundant)=[]; % Discard redundant lines signo(redundant)=[]; redundant =[]; for l = find(signo<0), % For each remaining negative minimum line ind = find((m(3,:)>m(3,l)-thresinterval)&(m(3,:)0); % Search for positive maxima near it if length(ind)>1, % If more than one ----> redundancy aux = abs(w(m(3,ind),3)./(m(3,ind)'-m(3,l))); % auxiliary variable: height over distance [mx,indmx]=max(aux); ind2=ind; aux(indmx)=[]; ind2(indmx)=[]; if all((mx./aux)>peakcriteria), redundant = [redundant ind2]; %#ok % RULE 2 else [aux,aux2]=min(abs(m(3,l)-m(3,ind))); %#ok ind(aux2)=[]; % RULE 1 redundant = [redundant ind]; %#ok end end end if ff==1 % axes(fig1); plot(fig1,m(1,redundant),w(m(1,redundant)),'*r') % axes(fig3); plot(fig3,m(3,redundant),w(m(3,redundant),3),'*r') if ~isempty(redundant) ll=[ll {'redundant mm lines'}]; end end m(:,redundant)=[]; % Discard redundant lines signo(redundant)=[]; %%%% isolated maximum lines resulting from Discarded redundant ind = find( ((m(1,2:end-1)-m(1,1:end-2))>thresinterval) ... & (m(1,3:end)- m(1,2:end-1))>thresinterval)+1; if size(m,2)<2 && ~isempty(ind), ind=1; end % when only one maximum %16DEZ08 if ff==1 % axes(fig1); legend(fig1,['WT_1',ll],'Location','NorthEastOutside') % axes(fig3); legend(fig3,['WT_3',ll],'Location','NorthEastOutside') % axes(fig1); plot(fig1,m(1,ind),w(m(1,ind)),'+m') % axes(fig3); plot(fig3,m(3,ind),w(m(3,ind),3),'+m') if ~isempty(ind) ll=[ll {'isolated mm lines'}]; end % axes(fig1); legend(fig1,['WT_1',ll],'Location','NorthEastOutside') % axes(fig3); legend(fig3,['WT_3',ll],'Location','NorthEastOutside') end m(:,ind) = []; %Discard isolated maximum lines signo(ind)=[]; if size(m,2)<2 m=[]; signo=[]; end eliminar=[]; %%%%extra protection% 23MAR09 % discard if no peak before and after messages.setup.wavedet.pictime ms for ii=1:size(m,2) pa = picant(w(max(1,m(2,ii)-round(messages.setup.wavedet.pictime*messages.setup.wavedet.freq)):m(2,ii),2),m(2,ii)); % first peak before detected qrs position at scale 2 pp = picpost(w(m(2,ii):min(size(w,1),m(2,ii)+round(messages.setup.wavedet.pictime*messages.setup.wavedet.freq)),2),m(2,ii)); %if isempty(pa) || isempty(pp) if isempty(pa) && isempty(pp) %NOV2011 eliminar=[eliminar ii]; %#ok end end if ff==1 % axes(fig1); plot(fig1,m(1,eliminar),w(m(1,eliminar)),'.r') % axes(fig3); plot(fig3,m(3,eliminar),w(m(3,eliminar),3),'.r') if ~isempty(eliminar) ll=[ll {'extra protection'}]; end % axes(fig1); legend(fig1,['WT_1',ll],'Location','NorthEastOutside') % axes(fig3); legend(fig3,['WT_3',ll],'Location','NorthEastOutside') end m(:,eliminar)=[]; signo(eliminar)=[]; % QRS peak detection / wavelet Zero cross detection timelap = ceil(messages.setup.wavedet.timelapthr*messages.setup.wavedet.freq); % the two maximum lines defining a QRS % should not be separated more than timelapthr time = []; aux=[]; auxm=[]; if size(m,2)>1 % 18 OUT2011 for l = find(signo>0), % For each positive maximum line if (l==1) % Special case: first line if (signo(2)<0)&&(m(1,2)-m(1,1) aux=[aux abs(w(m(1,l))-w(m(1,l+1)))]; %#ok auxm=[auxm; [m(1,l) m(1,l+1)]]; %#ok end elseif (l==size(m,2)) % Special case: last line if (signo(l-1)<0)&&(m(1,end)-m(1,end-1) aux=[aux abs(w(m(1,l-1))-w(m(1,l)))]; %#ok auxm=[auxm ; [m(1,l-1) m(1,l)]]; %#ok end elseif signo(l+1)<0 && ((signo(l-1)>0) ... || ((m(1,l+1)-m(1,l))<(m(1,l)-m(1,l-1)))) ind = zerocros(w(m(1,l):min(m(1,l)+timelap,size(w,1)),1)); time = [time ind+m(1,l)-1]; %#ok aux=[aux abs(w(m(1,l))-w(m(1,l+1)))]; %#ok auxm=[auxm;[ m(1,l) m(1,l+1)]]; %#ok elseif signo(l-1)<0, ind = zerocros(w(m(1,l-1):min(m(1,l-1)+timelap,size(w,1)),1)); time = [time ind+m(1,l-1)-1]; %#ok aux=[aux abs(w(m(1,l-1))-w(m(1,l)))]; %#ok auxm=[auxm;[ m(1,l-1) m(1,l)]]; %#ok end end end if ff==1 plot(fig2,time,messages.sig(time),'ob') ll_ECG={'ECG','QRS candidates'}; legend(fig2,ll_ECG,'Location','NorthEastOutside') end % Refractary period after a QRS detection. Retain only the waves with % more energy within the refractary period. if ~isempty(time), rr = (time(2:end)-time(1:end-1)); ind = find(rr % 18JUL2011 if ii==2, ind(auxi)=ind(auxi)+1; end end % ind=ind+1; % olde version % always the second one is eliminated!!! if ff==1 % axes(fig2); plot(fig2,time(ind),messages.sig(time(ind)),'xr') % axes(fig1); plot(fig1,m(1,ind),w(m(1,ind)),'xr') % axes(fig3); plot(fig3,m(3,ind),w(m(3,ind),3),'xr') if ~isempty(ind) ll=[ll {'rejected by the refractary period'}]; ll_ECG=[ll_ECG {'rejected by the refractary period'}]; end % axes(fig2); legend(fig2,ll_ECG,'Location','NorthEastOutside') % axes(fig1); legend(fig1,['WT_1',ll],'Location','NorthEastOutside') % axes(fig3); legend(fig3,['WT_3',ll],'Location','NorthEastOutside') end time(ind)=[]; %RUTE 27Jun11 aux(ind)=[]; if abs(samp(time(1)) - lastqrs)< refrper*messages.setup.wavedet.freq, % Refractory period for time(1)=[]; aux(1)=[];%#ok % last beat of previous end % fragment end % search back if no detection in messages.setup.wavedet.rrmaxlim RR median if ~isempty(time), %%%%%%%%%%%%%%%% caso em que rr tem dimensao inferior ao necessario if length(time)>1 %%%%%%%%%%%%%%%%introduzido a 17/05/02 Rute rr = ([max(samp(time(1))-lastqrs,time(1)) time(2:end)-time(1:end-1)]); %rr = ([samp(time(1))-lastqrs, time(2:end)-time(1:end-1)]); rrmed = [rr(1) 0.5*(rr(1)+rr(2)) median([rr(3:end);rr(2:end-1);rr(1:end-2)])]; ind = find((rr(2:end)>messages.setup.wavedet.rrmaxlim*rrmed(1:end-1)) & (rr(1:end-1)>messages.setup.wavedet.rrmaxmaxlim*messages.setup.wavedet.freq) | rr(2:end)>messages.setup.wavedet.rrmaxlimsec*messages.setup.wavedet.freq); %%%% 22NOV2011 if messages.setup.wavedet.refrper_reduc>0 && refrper>0.250 % 22NOV2011 while sum(rrmed0.6 refrper=refrper*messages.setup.wavedet.refrper_reduc; end % 22NOV2011 if messages.setup.wavedet.refrper(end)~=refrper messages.setup.wavedet.refrper(end+1)=refrper; messages.setup.wavedet.refrperdef(end+1)=samp(time(1)); end end if ff==1 if ~isempty(ind) ll=[ll {'searchback'}]; ll_ECG=[ll_ECG {'searchback'}]; % axes(fig2); plot(fig2,time(ind),messages.sig(time(ind))+50,'vc') legend(ll_ECG,'Location','NorthEastOutside') % axes(fig1); plot(fig1,time(ind),w(time(ind),1)+200,'vc') % axes(fig3); plot(fig3,time(ind),w(time(ind),3)+200,'vc') % axes(fig1); legend(fig1,'WT_1',ll,'Location','NorthEastOutside') % axes(fig3); legend(fig3,'WT_3',ll,'Location','NorthEastOutside') end end for l = ind, % For all rr intervals greater than 1.5RR interv = (time(l)+ceil(refrper*messages.setup.wavedet.freq)) : (time(l+1)-ceil(refrper*messages.setup.wavedet.freq)); if length(interv)>messages.setup.wavedet.rrmax_rbt*messages.setup.wavedet.freq, % for robustness % [nuevo, messages] = searchbk(w(interv,:),interv(1),eps(:,nlead)',messages.setup.wavedet.freq,messages.setup.wavedet.th_schb,messages); [nuevo, messages] = searchbk(w(interv,:),interv(1),eps(:,nlead)',messages.setup.wavedet.freq,th,messages); %FEB16_2012 % searchbk returns the new time of occurrence of a QRS time = [time nuevo]; %#ok % New times are added % time = sort(time); % and sorted if ff==1 % axes(fig2); plot(fig2,nuevo,messages.sig(nuevo),'oc') if ~isempty(nuevo) ll_ECG=[ll_ECG {'new candidates by searchback'}]; %#ok end legend(fig2,ll_ECG,'Location','NorthEastOutside') end end end %%%%%%%%%%%%%%%%introduzido a 17/05/02 Rute else % only one detection DEZ2011 if time > max(messages.setup.wavedet.gapthrs,ceil(refrper*messages.setup.wavedet.freq))%initial gap % 24ABRIL2010 % if time > messages.setup.wavedet.gapthrs %initial gap if (~exist('th','var') || isnan(th)), th = messages.setup.wavedet.thmax ; end [nuevo, messages]= searchbk(w(1:(time-ceil(refrper*messages.setup.wavedet.freq))),1,eps(:,nlead)',messages.setup.wavedet.freq,th,messages); time = [time nuevo]; end end else % in case there is no detection, searchback anyway if (~exist('th','var') || isnan(th)), th = messages.setup.wavedet.thmax ; end %nuevo = searchbk(w,1,eps,messages.setup.wavedet.freq, messages.setup.wavedet.th_schb); %Rute 02.Dec.04 [nuevo, messages]= searchbk(w,1,eps(:,nlead)',messages.setup.wavedet.freq, th,messages); time = nuevo; if ff==1 % axes(fig2); plot(fig2,nuevo,messages.sig(nuevo),'oc') if ~isempty(nuevo) ll_ECG=[ll_ECG {'new candidates by searchback'}]; end legend(fig2,ll_ECG,'Location','NorthEastOutside') end end if ~isempty(time), time = sort(time); % Rute 14DEz if length(time)>1 rr = ([samp(time(1))-lastqrs, time(2:end)-time(1:end-1)]); rrmed = [rr(1) 0.5*(rr(1)+rr(2)) median([rr(3:end);rr(2:end-1);rr(1:end-2)])]; %RUTE OUT2011 else rrmed =1; end if length(w)-time(end) > messages.setup.wavedet.gapthrs*rrmed, % If there is a final "gap" interv= (time(end)+ceil(refrper*messages.setup.wavedet.freq) : length(w)); %RUTE OUT2011 if length(interv)>messages.setup.wavedet.rrmax_rbt*messages.setup.wavedet.freq, [nuevo, messages] = searchbk(w(interv,:),interv(1),eps(:,nlead)',messages.setup.wavedet.freq, th,messages); time = [time nuevo]; if ff==1 % axes(fig2); plot(fig2,nuevo,messages.sig(nuevo),'oc') if ~isempty(nuevo) ll_ECG=[ll_ECG {'new candidates by searchback'}]; end legend(fig2,ll_ECG,'Location','NorthEastOutside') end end end %%% The first and last beats must be complete, to detect P-wave and T-wave %%% %%% We use an overlap that assures that the beat will be complete always in %%% one of the segments. if (time(1) <= messages.setup.wavedet.pwaveout*messages.setup.wavedet.freq), time(1)=[]; 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. if ~isempty(lastqrs) time(samp(time)<= lastqrs + refrper*messages.setup.wavedet.freq)=[]; end if ~isempty(time) %%%%%%% Rute 06/05/02 caso time(indrep)=time % if beat before ultimo_anot in the previous segment %6AGO2007 if samp(time(1))<=ultimo_anot time(1)=[]; end if ~isempty(time) && (length(w)-time(end) < messages.setup.wavedet.twaveout*messages.setup.wavedet.freq), % si no ye a onda T drento time(end)=[]; % de sig end % If last beat's T-wave is not in 'sig', the beat is detected in next one if ~isempty(time) %Rute 10.04.05 timeqrs = [timeqrs samp(time)]; % QRS times lastqrs = samp(time(end)); end end intervalo = [numlatdet+1 numlatdet+length(time)]; % numeration of the beats processed in this segment numlatdet = intervalo(2); position.qrs(intervalo(1):intervalo(2)) = samp(time); % Fill QRS position end if ff==1 % axes(fig2); plot(fig2,time,messages.sig(time),'.g') ll_ECG=[ll_ECG {'final SL marks'}]; legend(fig2,ll_ECG,'Location','NorthEastOutside') % axes(fig1); legend(fig1,['WT_1',ll],'Location','NorthEastOutside') % axes(fig3); legend(fig3,['WT_3',ll],'Location','NorthEastOutside') end else intervalo=[];time=[]; %Rute 13Set06 end