Noninvasive Fetal ECG: The PhysioNet/Computing in Cardiology Challenge 2013 1.0.0

File: <base>/sources/rapr_at_fct.unl.pt/detectqrsmultichannel2.m (5,309 bytes)
function [qrs threshold auxvec ]=detectqrsmultichannel2(ecg,samplingfreq)

  L=size(ecg,2);
  numchannels=size(ecg,1);

  #extra filtering->inovation for detectqrsmultichannel_2
  newmovageragefiltsize=40;#ms
  movaveragekernel=ones(1,newmovageragefiltsize)/newmovageragefiltsize;
  for i=1:numchannels
    newecg(i,:)=filtfilt(movaveragekernel,1,ecg(i,:));
  endfor



  diffsignal=[zeros(numchannels,1),diff(newecg,1,2)];

  auxvec=zeros(1,L);
  windowtime=40;#ms related to qrs duration
  windowL=floor(windowtime*samplingfreq/1000);
  halfwindow=floor(windowL/2);


  peak=[ones(1,halfwindow+1),-ones(1,halfwindow)];

  for i=halfwindow+1:L-halfwindow
    for c=1:numchannels
      auxvec(i)+=abs(diffsignal(c,i-halfwindow:i+halfwindow)*peak');
    endfor
  endfor

  basicvec=auxvec;

  #replace peaks by area on a window time

   # auxvec=zeros(1,L);
   # newl=10;
   # for i=newl+1:L-newl
   #   auxvec(i)=sum(basicvec(i-newl:i+newl));
   # endfor


 

 ##################################################
 ## FIRST APPROACH ################################
 ###################################################


  ############### parameters that must be better tuned 

  threshold=50000;

  maximumqrsinterval=1400*samplingfreq/1000;
  ##reduction of threshold value is done in a local base and not globally as in
  ## the first version

  smallwindow=floor(400*samplingfreq/1000);##minimum QRS interval
  ############### 


  qrs=[];

  emptysegments=[1,length(auxvec)];

  


  while(!isempty(emptysegments)&&(threshold>10))

    

    for i=1:length(emptysegments)/2

       qrs=searchlocalmax(threshold, auxvec, qrs,
       			 emptysegments(2*i-1), emptysegments(2*i),
       			 maximumqrsinterval, smallwindow);

      # qrs=searchlocalmaxnew(threshold, auxvec, qrs,
      # 			    emptysegments(2*i-1), emptysegments(2*i),
      # 			    smallwindow);

    endfor

    if(!isempty(qrs))
      aux=zeros(1,length(auxvec));
      aux(qrs(:))=1;

      emptysegments=findemptysegments(aux, maximumqrsinterval);
    endif

    threshold=3/4*threshold;

    #debug
    #printf("size(qrs)=%d\n",size(qrs,2));fflush(stdout);

  endwhile

  

  minimumnumberqrsaux=50;

  if(length(qrs)>minimumnumberqrsaux)

  #repeat process to
  #locate possible missing qrs using new maximumqrsinterval
  
    medianqrsperiod=median(diff(qrs));
    smallwindow=floor(min(3/4*medianqrsperiod,smallwindow));#new
    maximumqrsinterval=max(floor(5/4*medianqrsperiod),2*smallwindow+10);

    refthreshold=threshold;

    aux=zeros(1,length(auxvec));
    aux(qrs(:))=1;
    
    emptysegments=findemptysegments(aux, maximumqrsinterval);

    while(!isempty(emptysegments)&&(threshold/refthreshold>0.1))

    

      for i=1:length(emptysegments)/2

	qrs=searchlocalmax(threshold, auxvec, qrs,
			   emptysegments(2*i-1), emptysegments(2*i),
			   maximumqrsinterval, smallwindow);
      endfor

      if(!isempty(qrs))
	aux=zeros(1,length(auxvec));
	aux(qrs(:))=1;

	emptysegments=findemptysegments(aux, maximumqrsinterval);
      endif

      threshold=3/4*threshold;

      
      #printf("size(qrs)=%d\n",size(qrs,2));fflush(stdout);

    endwhile

  endif

  if(length(qrs)>1)
    assert(min(diff(qrs))>=smallwindow);
  endif


 #debug
 #printf("after first approach siz qrs is %d\n",size(qrs,2));fflush(stdout);


 ##################################################
 ## SECOND APPROACH  redefining maximumqrsinterval and smallwindow
 ###################################################

 # threshold=50000;

#  ##redefining thresholds

#  differences=diff(qrs);

#  avgdiff=mean(differences);


#  maximumqrsinterval=floor(avgdiff+120*samplingfreq/1000);

#  smallwindow=floor(avgdiff-160*samplingfreq/1000);

#  ###############################################

#  #repeating the cycle

#  qrs=[];

#  emptysegments=[1,length(auxvec)];

# #printf("length emptysegments is %d and threshold is %d\n",length(emptysegments),threshold);fflush(stdout);

  

#   while(!isempty(emptysegments)&&(threshold>10))

    

#     for i=1:length(emptysegments)/2

#       qrs=searchlocalmax(threshold, auxvec, qrs,
# 			 emptysegments(2*i-1), emptysegments(2*i),
# 			 maximumqrsinterval, smallwindow);

#     endfor

#     if(!isempty(qrs))
#       aux=zeros(1,length(auxvec));
#       aux(qrs(:))=1;

#       emptysegments=findemptysegments(aux, maximumqrsinterval);
#     endif

    

#     threshold=3/4*threshold;

#     #debug
#     #printf("size(qrs)=%d\n",size(qrs,2));fflush(stdout);

#   endwhile

  #####################################################


  if(length(qrs)>1)
    assert(min(diff(qrs))>=smallwindow);
  endif

  qrs=replacebylocmax(qrs,halfwindow,sum(ecg.^2));
    
endfunction



function res=replacebylocmax(setofpoints,halfwindow,abssignal)

  numpoints=length(setofpoints);

  res=zeros(1,numpoints);

  L=length(abssignal);


  for i=1:numpoints

    if(setofpoints(i)>halfwindow)

      if(setofpoints(i)<=L-halfwindow)

	[a order]=max(abssignal(setofpoints(i)-halfwindow:\
				setofpoints(i)+halfwindow));

	res(i)=setofpoints(i)+order-halfwindow;

      else

	[a order]=max(abssignal(setofpoints(i)-halfwindow:L));

	res(i)=setofpoints(i)+order-halfwindow;

      endif

    else

      [a order]=max(abssignal(1:setofpoints(i)+halfwindow));

      res(i)=order;
    endif

  endfor

endfunction