function [pos,picon,picoff,janelas,messages]=twave3D(w,timenew,i,freq,S,QRSoff,samp,rrmed,messages) % %[pos,picon,picoff,janelas]=twave3D(w,timenew,i,freq,S,QRSoff,samp,rrmed) % % multilead T wave delineation % %Input Parameters: % w: matrix with WT scales 1 to 5 % timenew: QRS times in inedexes refering the interval included in the current excerpt (borders excluded) % i: beat number % freq: sampling frequency (heasig.freq) % S: lattest S wave position found in any lead % QRSoff: lattest QRS end position found in any lead % samp: samples included in the current excerpt (borders excluded) % rrmed: Exponentially averaged RR % %Output Parameters: % pos: fiducial marks structure (position) % picon: position of the first relevant modulos maximum in the wavelet % picoff: position of the last relevant modulos maximum in the wavelet % janelas: T wave seach windows % % Rute Almeida % Last update: Rute Almeida 05AGO2011 % % Designed for MATLAB Version R12; tested with MATLAB Version R13 % %%%%%% Constants and Thresholds !!!!!!!!!!!!!!!!!!!!!!!!! if ~isfield(messages.setup.wavedet,'umbraldetT') messages.setup.wavedet.umbraldetT = 0.25; % We use umbraldet*sqrt(mean(w(time(i):time(i+1),4).^2)) end if ~isfield(messages.setup.wavedet,'umbralsig') messages.setup.wavedet.umbralsig = 1/8; end if ~isfield(messages.setup.wavedet,'Kton') messages.setup.wavedet.Kton = 4; % 2 4! end if ~isfield(messages.setup.wavedet,'inivent_tol') messages.setup.wavedet.inivent_tol = 0.1; end if ~isfield(messages.setup.wavedet,'inivent_tol_S') messages.setup.wavedet.inivent_tol_S=0.05; % sec end if ~isfield(messages.setup.wavedet,'finvent_tol') messages.setup.wavedet.finvent_tol=0.240;% sec end if ~isfield(messages.setup.wavedet,'finvent_max') messages.setup.wavedet.finvent_max=0.6;% sec end if ~isfield(messages.setup.wavedet,'min_vent') messages.setup.wavedet.min_vent=0.1;%sec end if ~isfield(messages.setup.wavedet,'Tmax_Tmin_time_min') messages.setup.wavedet.Tmax_Tmin_time_min=0.15;%sec end if ~isfield(messages.setup.wavedet,'Tmax_Tmin_bifasic') messages.setup.wavedet.Tmax_Tmin_bifasic=2.5; end Kton=messages.setup.wavedet.Kton; Ktoff=messages.setup.wavedet.Kton; messages.warnings=[messages.warnings {'Recall that in twave3D ktoff=kton.'}]; umbraldetT = messages.setup.wavedet.umbraldetT; umbralsig = messages.setup.wavedet.umbralsig; inivent_tol= messages.setup.wavedet.inivent_tol; inivent_tol_S=messages.setup.wavedet.inivent_tol_S; finvent_tol=messages.setup.wavedet.finvent_tol; finvent_max= messages.setup.wavedet.finvent_max; min_vent=messages.setup.wavedet.min_vent; Tmax_Tmin_time_min= messages.setup.wavedet.Tmax_Tmin_time_min;%sec Tmax_Tmin_bifasic=messages.setup.wavedet.Tmax_Tmin_bifasic;% extra criteria %%%%%%%%%%%%%%%%%%%%%%%%%%%% janelas=[];%%31May05 % Initialization of auxiliary variables T = []; Tprima=[]; picon=[]; picoff=[]; Ton=[]; Toff=[]; tipoT=[]; % minapos = []; minppos=[]; maxapos=[]; maxppos=[]; mina=[]; minp=[]; maxa=[]; % maxp=[]; picon_keep=[];%multileadchange picoff_keep=[];%multileadchange lead_keep=[];%multileadchange inivent = round(inivent_tol*freq); % Begining of window if ~isempty(S), % If there is an S wave inivent = max(inivent, S-timenew(i)+round(inivent_tol_S*freq)); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% changed 13/06/02 Rute if rrmed <= freq, %if rrmed >= freq, finvent = round(finvent_max*freq); % End of window else finvent = round(rrmed*finvent_max); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% changed 13/06/02 Rute % using timenew from diffferent leads ty ca dist less tahn 0.24 sec!!! if i~=length(timenew), % For last beat in the segment finvent = min(finvent,timenew(i+1)-timenew(i)-round(finvent_tol*freq)); else finvent = min(finvent,timenew(i)-timenew(i-1)-round(finvent_tol*freq)); end % We work at scale scale (in general). if isempty(QRSoff), % Should never happen, but... % begwin = inivent + timenew(i); begwin = inivent; else % begwin = max(inivent + timenew(i), QRSoff+1); begwin = max(inivent , QRSoff+1-timenew(i)); end %endwin = min(finvent + timenew(i),length(w)); %% Rute 20/05/02 endwin = min(finvent ,length(w)); %% Rute 20/05/02 janelas=[janelas; i begwin endwin];%31May05 if ~isempty(begwin+1:endwin ) % 22.04.05 % Positive maxima and negative minima in the window maxpos = begwin + modmax(w(begwin+1:endwin ),2,0,+1); minpos = begwin + modmax(w(begwin+1:endwin ),2,0,-1); [maxim ind] = max(w(maxpos )); % The biggest of the positive maxpos = maxpos(ind); [minim ind] = min(w(minpos )); % The biggest of the negative minpos = minpos(ind); if isempty(maxpos), % If no local positive maximum % The maximum will be the first % or the last sample if (w(begwin )>=w(endwin )) && w(begwin )>0, maxpos = begwin; maxim = w(maxpos ); elseif (w(endwin )>=w(begwin )) && w(endwin )>0, maxpos = endwin; maxim = w(maxpos ); end end if isempty(minpos), % if no local negative minimum % the minimum will be the first % or the last sample if (w(begwin )<=w(endwin )) && w(begwin )<0, minpos = begwin; minim = w(minpos ); elseif (w(endwin )<=w(begwin )) && w(endwin )<0, minpos = endwin; minim = w(minpos ); end end absmax = abs(maxim); absmin = abs(minim); if iumbraldetT*veficaz)|(absmin>umbraldetT*veficaz)); % Rute 18/06/02 if endwin-begwin<(min_vent*freq) % se a janela tem amplitude menor do que min_vent seg enato nao existe onda T hay_onda =0; end % Is there a wave? if hay_onda, if absmax >= absmin, % the greatest modulus maximum is the maximum % Now we search the two minima nearest to maxpos, one before and one after minapos = max(modmax(w(begwin+1:maxpos-1 ),2,0,-1)); minapos = begwin + minapos; % Position of the negative minimum before the maximum if isempty(minapos) && (maxpos ~= begwin) && (w(begwin )<0), minapos = begwin;% If no local minimum before the maximum, take the first sample end minppos = min(modmax(w(maxpos+1:endwin ),2,0,-1)); minppos = maxpos + minppos; % Position of the positive maximum after the minimum if isempty(minppos) && (maxpos ~= endwin) && (w(endwin )<0), minppos = endwin; % If no local minimum after the maximum, take the last sample end mina = abs(w(minapos )); % Amplitude of minimum before maximum minp = abs(w(minppos )); % Amplitude of minimum after maximum if (mina < umbralsig*absmax), % If mina is not big enough mina =[]; % forget it elseif (maxpos-minapos>Tmax_Tmin_time_min*freq), %or if ther are more than 150 ms to maxpos mina = []; end if (minp < umbralsig*absmax), % If minp is not big enough minp =[]; % forget it elseif (minppos-maxpos>Tmax_Tmin_time_min*freq), % and also if there are more than 150 ms to maxpos minp =[]; end if ~isnan(mina)&~isnan(minp), %#ok %%% NUEVO JP if (mina >= minp)&&(minp < umbralsig*absmax*Tmax_Tmin_bifasic), minp = []; elseif (minp> mina)&&(mina < umbralsig*absmax*Tmax_Tmin_bifasic), mina = []; end end % Test which modulus maxima are significative and find zero crossings if isempty(mina), if isempty(minp), tipoT = 2; % only upwards T wave if maxpos - minapos > 2, % if not !!!!!!!!!!! ind = zerocros(flipud(w(minapos:maxpos ))); %Scale 3 !!! % also in scale 4!!!!!!! 03.Dec.04 T = maxpos - ind +1; % Zero crossing = T wave position picoff = maxpos; %wavelet peak to detect offset elseif isempty(minapos); % If there were no minimum, there is no zero crossing T = picant (w(begwin:maxpos ),maxpos); % Take the minimum at scale 4 if ~isempty(T) %%%%%%%%%%%% 14/06/02 Rute picoff = maxpos; else picoff = []; % if did not exist a peak in scale 4 there is no T end %%%%%%%%%%%% 14/06/02 Rute else %%%%%%%%%%%%%%%%%%%%% nao faz nada!!!!!!! % 12/06/02 Rute messages.warnings=[messages.warnings {'unknown case: unable to classify T wave.'}]; end else % minp exists (is significative) but mina not tipoT = 0; %normal T wave if minppos -maxpos >2, % if not!!!!!!??? ind = zerocros(w(maxpos:minppos )); %% 07/06/02 Rute % also in scale 4!!!!!!! 03.Dec.04 % if isempty(ind) %%%%%%%%%%%%%%Rute 03/09/02 % ind = zerocros(w(maxpos:minppos)); % end %%%%%%%%%%%%%%Rute 03/09/02 T = maxpos + ind -1; picon = maxpos; % For determining onset and offset picoff = minppos; else %%%%%%%%%%%%%%%%%%%%% nao faz nada!!!!!!! % 12/06/02 Rute messages.warnings=[messages.warnings {'unknown case: unable to classify T wave.'}]; end end else if isempty(minp), % mina exists (is significative) but minp not tipoT = 1; %inverted T wave if maxpos -minapos >2, % if not !!!!!!!!! ind = zerocros(w(minapos:maxpos)); % wavelet zero crossing is T wave peak %% 07/06/02 Rute % also in scale 4!!!!!!! 03.Dec.04 % if isempty(ind)%%%%%%%%%%%%%%Rute 03/09/02 % ind = zerocros(w(minapos:maxpos )); % wavelet zero crossing is T wave peak %% 03/09/02 Rute % end %%%%%%%%%%%%%%Rute 03/09/02 T = minapos + ind -1; picon = minapos; picoff = maxpos; else %%%%%%%%%%%%%%%%%%%%% nao faz nada!!!!!!! % 12/06/02 Rute messages.warnings=[messages.warnings {'unknown case: unable to classify T wave.'}]; end else % both mina and minp are significative. Biphasic wave. tipoT = 5; % biphasic neg-pos T wave if maxpos - minapos > 2, %!!!!!!!!!!!! ind = zerocros(flipud(w(minapos:maxpos ))); %% 07/06/02 Rute % also in scale 4!!!!!!! 03.Dec.04 % if isempty(ind) %%%%%%%%%%%%%%Rute 03/09/02 % ind = zerocros(flipud(w(minapos:maxpos ))); %% 03/09/02 Rute % end%%%%%%%%%%%%%%Rute 03/09/02 T = maxpos - ind +1; picon = minapos; else %%%%%%%%%%%%%%%%%%%%% nao faz nada!!!!!!! % 12/06/02 Rute messages.warnings=[messages.warnings {'unknown case: unable to classify T wave.'}]; end if minppos - maxpos > 2, %!!!!!!!!!!!! ind = zerocros(flipud(w(maxpos:minppos ))); %% 07/06/02 Rute % also in scale 4!!!!!!! 03.Dec.04 % if isempty(ind)%%%%%%%%%%%%%%Rute 03/09/02 % ind = zerocros(flipud(w(maxpos:minppos ))); %% 03/09/02 Rute % end %%%%%%%%%%%%%%Rute 03/09/02 %Tprima = maxpos + ind -1; %18.11.05 Tprima = minppos- ind +1; picoff = minppos; else %%%%%%%%%%%%%%%%%%%%% nao faz nada!!!!!!! % 12/06/02 Rute messages.warnings=[messages.warnings {'unknown case: unable to classify T wave.'}]; end end end else % If the greatest modulus maximum is the minimum % Search two maxima, one before and one after the minimum maxapos = max(modmax(w(begwin+1:minpos-1 ),2,0,1)); maxapos = begwin + maxapos; if isempty(maxapos) && (minpos ~= begwin) && (w(begwin )>0), maxapos = begwin; end maxppos = min(modmax(w(minpos+1:endwin ),2,0,1)); maxppos = minpos + maxppos; if isempty(maxppos) && (minpos ~= endwin) && (w(endwin )>0), maxppos = endwin; end maxa = abs(w(maxapos )); maxp = abs(w(maxppos )) ; % See if they are significative if (maxa < umbralsig*absmin) maxa =[]; elseif (minpos-maxapos>Tmax_Tmin_time_min*freq), maxa = []; end if (maxp < umbralsig*absmin), maxp =[]; elseif (maxppos-minpos>Tmax_Tmin_time_min*freq), maxp = []; end if ~isnan(maxa)&~isnan(maxp), %#ok %%% NUEVO JP if (maxa >= maxp)&&(maxp < umbralsig*absmin*Tmax_Tmin_bifasic), maxp = []; elseif (maxp> maxa)&&(maxa < umbralsig*absmin*Tmax_Tmin_bifasic), maxa = []; end end % Test which modulus maxima are significative and find zero crossings if isempty(maxa), if isempty(maxp), tipoT = 3; % only downwards T wave if minpos - maxapos > 2, %!!!!!!!! ind = zerocros(flipud(w(maxapos:minpos ))); %Scale 3 % also in scale 4!!!!!!! 03.Dec.04 % if isempty(ind) %%%%%%%%%%%%%%Rute 03/09/02 % ind = zerocros(flipud(w(maxapos:minpos ))); % end %%%%%%%%%%%%%%Rute 03/09/02 T = minpos - ind +1; picoff = minpos; elseif isempty(maxapos); % If there were no maximum, there is no zero crossing. T = picant (w(begwin:minpos ),minpos); % menimo en escala 4. if ~isempty(T) %%%%%%%%%%%% 14/06/02 Rute picoff = minpos; else picoff = []; % if did not exist a peak in scale 4 there is no T end %%%%%%%%%%%% 14/06/02 Rute else %%%%%%%%%%%%%%%%%%%%% nao faz nada!!!!!!! % 12/06/02 Rute messages.warnings=[messages.warnings {'unknown case: unable to classify T wave.'}]; end else % maxp is signficative, but not maxa tipoT = 1; %inverted T wave if maxppos -minpos >2, % !!!!!! ind = zerocros(w(minpos:maxppos )); %% 07/06/02 Rute % also in scale 4!!!!!!! 03.Dec.04 % if isempty(ind) %%%%%%%%%%%%%%Rute 03/09/02 % ind = zerocros(w(minpos:maxppos )); %% 03/09/02 Rute % end %%%%%%%%%%%%%%Rute 03/09/02 T = minpos + ind -1; picon = minpos; % For calculating onset and offset picoff = maxppos; else %%%%%%%%%%%%%%%%%%%%% nao faz nada!!!!!!! % 12/06/02 Rute messages.warnings=[messages.warnings {'unknown case: unable to classify T wave.'}]; end end else if isempty(maxp), % maxa is significative, but not maxp tipoT = 0; %normal T wave if minpos -maxapos >2, ind = zerocros(w(maxapos:minpos )); %% 07/06/02 Rute % also in scale 4!!!!!!! 03.Dec.04 % if isempty(ind) %%%%%%%%%%%%%%%%%%%% 03/09/02 Rute % ind = zerocros(w(maxapos:minpos )); %% 03/09/02 Rute %end %%%%%%%%%%%%%%%%%%%% 03/09/02 Rute T = maxapos + ind -1; picon = maxapos; picoff = minpos; else %%%%%%%%%%%%%%%%%%%%% nao faz nada!!!!!!! % 12/06/02 Rute messages.warnings=[messages.warnings {'unknown case: unable to classify T wave.'}]; end else % both maxa and maxp are significative. Biphasic wave. tipoT = 4; % biphasic pos-neg T wave if minpos - maxapos > 2, %!!!!!!!!!!! ind = zerocros(flipud(w(maxapos:minpos ))); %% 07/06/02 Rute % also in scale 4!!!!!!! 03.Dec.04 % if isempty(ind) %%%%%%%%%%%%%%%%%%%% 03/09/02 Rute % ind = zerocros(flipud(w(maxapos:minpos ))); %% 03/09/02 Rute % end %%%%%%%%%%%%%%%%%%%% 03/09/02 Rute T = minpos - ind +1; picon = maxapos; else %%%%%%%%%%%%%%%%%%%%% nao faz nada!!!!!!! % 12/06/02 Rute % [i tipoT] disp('caso nao previsto; onda T nao marcada!') end if maxppos - minpos > 2, %!!!!!!!!!!!! ind = zerocros(flipud(w(minpos:maxppos ))); %% 07/06/02 Rute % also in scale 4!!!!!!! 03.Dec.04 % if isempty(ind) %%%%%%%%%%%%%%%%%%%% 03/09/02 Rute % ind = zerocros(flipud(w(minapos:maxpos ))); %% 03/09/02 Rute % end %%%%%%%%%%%%%%%%%%%% 03/09/02 Rute %Tprima = minpos + ind -1; %18.11.05 DUVIDA Tprima = maxppos- ind +1; picoff = maxppos; else %%%%%%%%%%%%%%%%%%%%% nao faz nada!!!!!!! % 12/06/02 Rute messages.warnings=[messages.warnings {'unknown case: unable to classify T wave.'}]; end end end end % T wave onset and offset detection %if isempty(T), picon=[]; picoff=[]; end picon_keep=[picon_keep picon]; %multileadchange picoff_keep=[picoff_keep picoff];%multileadchange lead_keep=[lead_keep 4];%multileadchange if ~isempty(picon), Ton = searchon (picon, w(max(begwin,picon-0.12*freq):picon ), Kton); end if ~isempty(picoff), Toff=searchoff(picoff, w(picoff:min([size(w,1) picoff+0.12*freq ]) ) , Ktoff); if (Toff > endwin), Toff = endwin; end end else tipoT=9; messages.warnings=[messages.warnings {'unknown case: unable to find T wave in multilead approach using scale 4.'}]; end %% utilizar a escala 5 07/06/02 Rute %%%%%%%%%%%%%%%%%%%%%%%%%%% end % Filling the structure with positions if isempty(Ton), Ton = NaN; end; if isempty(Toff), Toff = NaN; end; if isempty(T), T=NaN; end; if isnan(T), picon_keep=[picon_keep NaN]; %multileadchange picoff_keep=[picoff_keep NaN];%multileadchange lead_keep=[lead_keep NaN];%#ok %multileadchange end if isempty(Tprima), Tprima=NaN; end; if isempty(tipoT), tipoT=NaN; end; pos.Ton= Ton+samp(1)-1+timenew(i)-1; pos.Toff= Toff+samp(1)-1+timenew(i)-1; pos.T= T+samp(1)-1+timenew(i)-1; pos.Tprima= Tprima+samp(1)-1+timenew(i)-1; pos.Ttipo= tipoT; % T = []; Tprima=[]; picon=[]; picoff=[]; Ton=[]; Toff=[]; tipoT=[]; % minapos = []; minppos=[]; maxapos=[]; maxppos=[]; mina=[]; minp=[]; maxa=[]; % maxp=[]; %end % position.Ton(intervalo(1):intervalo(2)) = pos.Ton+samp(1)-1; % position.Toff(intervalo(1):intervalo(2))= pos.Toff+samp(1)-1; % position.T(intervalo(1):intervalo(2)) = pos.T+samp(1)-1; % position.Tprima(intervalo(1):intervalo(2)) = pos.Tprima+samp(1)-1; % position.Ttipo(intervalo(1):intervalo(2)) = pos.Ttipo; % pos.Ton % Ton = pos.Ton(i) % Toff= pos.Toff(i) % T= pos.T(i) % Tprima = pos.Tprima(i) % Ttipo= pos.Ttipo(i); %timenew(i) %picon_keep picoff=picoff_keep+timenew(i)-1; picon=picon_keep+timenew(i)-1;