ECG-Kit 1.0

File: <base>/common/wavedet/twave3D.m (22,204 bytes)
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 i<length(timenew),
        veficaz = sqrt(mean(w .^2)); % all w 03.Dec.04 interval was restricted before
    else                        % if last beat of the segment
        veficaz = sqrt(nanmean(w.^2)); % all w 03.Dec.04 interval was restricted before
    end
    
    hay_onda = ((absmax>umbraldetT*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<AND2> %%% 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<AND2> %%% 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<NASGU> %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;