ECGPUWAVE 1.3.4

File: <base>/src/ecgpuwave/ecgpuwave.f (16,654 bytes)
C  Adaptacion para usar con "wave" y "command line arguments"
C  
C    Pablo Laguna    13 febrero 1994
c
c        ======================================================
C          ECGMAIN (DETECCION QRS)
C          AUTOR: PABLO LAGUNA/ RAIMON JANE/ EUDALD BOGATELL 
C          DATA: 22-MAIG-87
C          Adaptacio: 19-novembre-87 (Ampliacio ona P: 2-2-88)
C                               (Finestres filtres PB:11-3-88)
C                     (Mateixa normalitzacio continua:10-4-89)
C            (ventanas P-QRS-T, normalizacion en todo:15-6-89)
C	   Adaptacio: deteccio punts sig. (Eudald Bogatell 1-6-91)
C	   Adaptacio: David Vigo Anglada. (9-1992)
C                     - tractament multiderivacional
C                     - lmnia de base 
C                     - segment ST
C          Modified: George B. Moody (6-Feb-2002) [1.0]
C                     - now compatible with WFDB library and wrappers
C                     - revised help text
C          Modified: George B. Moody (24-Feb-2006) [1.1]
C                     - fixed warning messages
C          Modified: George B. Moody (19 June 2006) [1.2]
C                     - increased size of 'arg' (command-line argument string)
C          Modified: Joe Ho (23 June 2008) [1.3]
C                     - can now specify signal numbers up to 99 using -s
C          Modified: Benjamin Moody (29 October 2018) [1.3.4]
C                     - increased size of command-line argument string
C
C=====================================================================

C       -----------------------------------------------------------------------
C       Copyright (C) 2002 Pablo Laguna
C
C       This program is free software; you can redistribute it and/or modify it
C       under the terms of the GNU General Public License as published by the
C       Free Software Foundation; either version 2 of the License, or (at your
C       option) any later version.
C
C       This program is distributed in the hope that it will be useful, but
C       WITHOUT ANY WARRANTY; without even the implied warranty of
C       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
C       General Public License for more details.
C
C       You should have received a copy of the GNU General Public License along
C       with this program; if not, write to the Free Software Foundation, Inc.,
C       59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
C
C       You may contact the author by e-mail (laguna@posta.unizar.es) or postal
C       mail (Dpt. Ingenieria Electrónica y Comunicaciones, Grupo de Tecnología
C       de las Comunicaciones (GTC), Centro Politécnico Superior. Universidad
C       de Zaragoza, María de Luna, 3 (Pol. Actur), Edificio A, Despacho 3.16,
C       50015 Zaragoza. Spain).  For updates to this software, please visit
C       PhysioNet (http://www.physionet.org/).
C       _______________________________________________________________________

C        ======================================================
C
C        ECG    Tiene la seqal original digitalizada
C        ECGPA  Tiene la seqal filtrada paso ALTO
C        ECGPB  Tiene la seqal filtrada paso bajo + paso alto
C        ECGDER Tiene la seqal ecgpb derivada
C        ECGQ   Es la seqal ECGDER elevada al cuadrado
C        ECGMW  Tiene la seqal ECGQ convolucionada con un escalon cuadrado
C        EMWDER Tiene la seqal ECGMW derivada
C        ELBA   Tiene la lmnea de base. 
C        ECGLB  Tiene el ecg corregido con la lmnea de base (ecg-elba)
C        DERFI  Tiene la derivada de 
C        DERI   Tiene la derivada de

 	 implicit real (a-h,o-z)

         dimension ecg(100000),ecgpa(100000),ecgpb(100000)
         dimension ecgder(100000)
         dimension ecgq(100000),ecgmw(100000),emwder(100000)
         dimension derfi(100000)
         dimension elba(100000),ecglb(100000),i_base(8000),qqrs(15,50)
         dimension iqrspa(8000),iqrsmw(8000),iqrs(8000),iqrst(8000)
         dimension iqt(8000)
         dimension iondaq(8000),iondat(8000),iqtc(8000),deri(100000)
	 dimension iqpos(8000),ispos(8000),isend(8000),itbeg(8000)
	 dimension itpos(8000)
         dimension ipbeg(8000),ippos1(8000),irrpos(8000)
         dimension ecgaux(100000)
	 dimension itend(8000),ipend(8000),iqbeg(8000),irpos(8000)
	 dimension iqend(8000),isbeg(8000),qrsdef(15,50),cont(15)
	 dimension ilead(4)
         dimension ecg1(100000),ecg2(100000),ecg3(100000),ecg4(100000)

	 logical fin
         character*3 fderiv
         character*1 espera
	 character*12 fd, faux, f1, f2, f3, an, anin, from, too, aux, bt   
         character*256 arg, f, fname, desc, units
         integer initval, group, fmt, spf, bsize, baseline, cksum
         integer putann, getann, wfdbquit, strtim, ij
 	 double precision gain, fm
	 double precision  sampfreq 
	 integer v(32), getvec, info, isigopen, osigfopen1, newheader
	 integer wfdbquiet, wfdbverbose, isqrs


 	 dimension morf(5,8000),buf5(76500),ampt(8000),durp(8000)
 	 dimension durt(8000)
	 dimension amprr(8000),ampr(8000),ampq(8000),amps(8000)
	 dimension ampp(8000)
	 dimension durpic(8000),qrsint(8000),durr(8000),durrr(8000)
	 dimension durq(8000)
	 dimension durs(8000),rrint(8000),print(8000),ppint(8000)
	 dimension qtint(8000)
	 dimension qtpint(8000),basel(8000),pendr(8000),itpos2(8000)
	 dimension idis(3,20), freV(8000), desV(8000)
	 dimension qtpcint(8000), qtcint(8000)
         dimension ipbeg_mean(30),ipend_mean(30),iqbeg_mean(30)
         dimension isend_mean(30),itend_mean(30)
         dimension ipbeg_lead(15,8000),ipend_lead(15,8000)
         dimension iqbeg_lead(15,8000),isend_lead(15,8000)
         dimension itend_lead(15,8000)
         dimension ST_ampl(8000),ST_pend(8000),ST_index(8000)
         dimension ST_area(8000)

	 character*4 tip(8000)
c        integer*2 aux
         integer*2 buf5,qqrs,qrsdef
         integer nlead,cont,esQRS,i_0,i_1
c 	 nqrs: nombre de qrs detectats i confirmats que tractarem
c 	 samp: interval de mostreig en ms
c	 iqrs: posicio dels complexes QRS detectats i confirmats
c	 irpos: vector que conti la posicio de l'ona R
c 	 ipbeg, ippos1, ipend: inici, pic i final de l'ona P
c 	 iqbeg, iqpos, iqend: inici, pic i final de l'ona Q
c 	 isbeg, ispos, isend: inici, pic i final de l'ona S
c 	 itbeg, itpos, itpos2, itend: inici, pics i final de l'ona T
c 	 basel: conte les linies de base de cada QRS
c	 idis: conte els posibles episodis de VT i VF
c	 nep: nombre d'episodis de VT i VF
c	 ampq, ampr, amps, amprr: amplituds de les ones Q, R, S i S' 
c	 durq, durr, durs, durrr: durades de les ones Q, R, S i R'
c	 rrint, ppint, print: intervals RR, PP i PR
c	 qtint, qtpint: intervals QT i QT de pic
c	 qtcint, qtpcint: intervals QT i QT de pic corretgits.
c	 durpic i pendr: duracio i pendent de la primera pujada de la R
c 	 morf: vector d'enters que ens informa de la morfologia del bateg
                                   
c           muestras anteriores (imu_an) igual a cero
 
c........................................................................
             imu_an=0
  	     imu_fi=0
	     ic=0
	     flag_qrs=0
	     flag_N=0 
	     nargs = iargc()
	     if (nargs.lt.4) then
 1    write(6,*) 'usage: ecgpuwave -r RECORD -a ANNOTATOR [OPTIONS ...]'
      write(6,*) 'where RECORD specifies the input, ANNOTATOR is the'
      write(6,*) 'output annotator name, and OPTIONS may include:'
      write(6,*) ' -f TIME    start at specified TIME'
      write(6,*) ' -i IANN    read QRS detections from IANN'
      write(6,*) ' -n PFLAG   specify beats to process (requires -i):'
      write(6,*) '             all (PFLAG=0; default)'
      write(6,*) '             normal beats only (PFLAG=1)'
      write(6,*) ' -s SIGNAL  analyze the specified SIGNAL (0-99):'
      write(6,*) '             default: SIGNAL= 0'
      write(6,*) ' -t TIME    stop at specified TIME'
	      return
	     end if
	     from='0'
	     too='0'
	     do 10 i=1, nargs/2
	       call getarg(2*i-1,arg)
	       if (arg.eq.'-r') then
	           call getarg(2*i,arg)
	          f=arg
	          if_r=1
	       else if 	(arg.eq.'-a') then
	           call getarg(2*i,an)
	           if_a=1
 	       else if 	(arg.eq.'-s') then
	          call getarg(2*i,arg)
	          ic=iachar(arg(1:1))-48
                  if (arg(2:2).ne.'') then
                     ic=ic*10+(iachar(arg(2:2))-48)
                  end if
	       else if 	(arg.eq.'-f') then
	           call getarg(2*i,from)
	       else if 	(arg.eq.'-t') then
	          call getarg(2*i,too)
	       else if 	(arg.eq.'-i') then
	          call getarg(2*i,anin)
	          flag_qrs=1
	       else if 	(arg.eq.'-n') then
		 call getarg(2*i,bt)
	         ibt=iachar(bt(1:1))-48
 	         if (ibt.eq.1) then 
                   flag_N=1 
	         end if
	       else   
                  write(6,*) 'ecgpuwave: unrecognized option ',arg
		  call help(2)
		  return
               end if
 10          continue

	  
	      if (if_r.ne.1.or.if_a.ne.1) then
		call help(3)
		return
 	      end if 


c     The '32' below is the maximum number of signals this program will
c     open.  (It will process only one of these signals, but it may be
c     necessary to open more than one signal in order to read the
c     desired signal.)  In order to read a record with a larger number
c     of signals, it may be necessary to increase this value.  If you do
c     so, increase the number of elements in v (above) and in sinfo (in
c     wfdbf.c) to match.
  	      i=isigopen(f,32)
	      i_0=0
	      i_1=1
              ii=setanninfo(i_0,an,i_1)
              ii=annopen(f,1)
	     
	      if (i.le.ic) then
 	       write(6,*) ' Signal',ic,' does not exist in the record'
	       return
	      end if 

                fm=sampfreq(f)
	        ifm=nint(fm) 
         
                i=getsiginfo(ic,fname,desc,units,gain,initval,group,fmt
     &               ,spf,bsize,adcres,ioffset,baseline,nsamp,cksum)
		if (gain.gt.0) then 
			igain=nint(gain)
		  else
		        igain=200
		end if

c            Becouse ST-T database has offset=o but is not true
		if (ioffset.eq.0) then 
		   do i=1,2*ifm
		     ig=getvec(v)
		     ioffset=ioffset+v(ic+1)
		    end do
                    ioffset=nint(ioffset/(2.*ifm)) 
	  	end if

	        imu_an=strtim(from)
                imu_fi=strtim(too)
	        if (imu_fi.eq.0) imu_fi=nsamp
	        if (imu_fi.le.imu_an) return

	      
	   
              if (flag_qrs.eq.1 ) then
                ii=setanninfo(0,anin,0)
                ii=annopen('+'//f,1)
c               ii=annopen1('+'//f,anin,0)
	       ij=getann(0,itime,i,ii,iii,iiii,aux)
	       if (itime.gt.imu_an+ifm) imu_an=itime-ifm
	      end if	            
  

	        rmax=1
	      	index=0
	        ilastqrs=0      
c  		write(6,*)  'ioffset', ioffset
c
c
c               used to write signals from the processing
c	       i=osigfopen1('pb',ic)
	     
               fin=.false.
               do while (fin.eqv..false.)

c                                             READ SIGNALS		 
	          i=isigsettime(imu_an+1)
	          is=0
	          if (imu_fi-imu_an.gt.100000-2*ifm) then
		      ns = 100000/ifm
	          else
	             ns = (imu_fi-imu_an+2*ifm)/ifm
	          end if
                  do i=1,100000
		    ig=getvec(v)
   		    if (ig.eq.-1.or.imu_an+i.ge.imu_fi+2*ifm) then
		     fin=.true.
	             ecg(i)=0. 
		    else 
		      ecg(i)=1.0*(v(ic+1)-ioffset)/igain
		    end if
	          end do

c				         INITIALICE AND SIGNAL PROCESSING                                                                            
                call inicializa_cero(iondat,iqtc,iqrspa,iqrsmw,iqrs,
     &                          iondaq,iqt)
               	call procesar(index,de_rmax,pa_rmax,pb_rmax,depb_rmax,
     &                             rq_rmax,rmw_rmax,rmd_rmax,
     &                   ifm,is,ns,ecg,ecgpa,ecgpb,ecgder,
     &                   ecgq,ecgmw,emwder,f,iret_pb,iret_pa,deri)
	
	  
 	        
c	         write(6,*) 'pa_rmax',pa_rmax,'pb_rmax',pb_rmax,'index',index

   		 	        

C					QRS DETECTION OR READING
            	if (flag_qrs.eq.0) then
       	         call detectar(index,ifm,is,ns,ecgpb,ecgder,ecgmw,emwder,iqrspa,
     *                   iqrsmw,iqrs,nqrs,f,rmax,pa_rmax,pb_rmax,
     *                   imu_an,ecg)
                 do j=1,nqrs
		   iqrst(j)=1        
c			los llamo a todos los latidos detectados normales
                 end do 
                else 
	           itime=imu_an
	           ii=iannsettime(imu_an)
	           n=1
	           ij=0
                   do while (itime.lt.imu_an+100000-2*ifm
     &                       .and.itime.lt.imu_fi)
  	            ij=getann(0,itime,i,ii,iii,iiii,aux)
                    esQRS=isqrs(i)
                    
	            if (ij.ne.0) then 
		     nqrs=n-1
	             fin=.true.
		     go to 20
	            end if
		    if (((flag_N.eq.0).and.(esQRS.eq.1)).or.((flag_N.eq.1).and.(i.eq.1))) then 
	             ibe=itime-imu_an-nint(0.2*ifm)
		     ien=itime-imu_an+nint(0.17*ifm)
	             call buscamaxmin(ibe,ien,ecgpa,imi,ymin,ima,ymax)

c                 write(6,*) 'flag_N ', flag_N, 'itime ', itime, ' i ', i
c	         write(6,*) 'itime', itime, 'imu_an', imu_an, ' imi',imi,' ymin',ymin,' ima',ima,' yma',ymax


                     if (abs(ymin).gt.abs(ymax)) then
			iqrs(n)=imi
		      else
			iqrs(n)=ima
                     end if
                     iqrst(n)=i
		     n=n+1
	            end if
 		   end do
	           nqrs=n-1
	        end if
 20             continue
	        index=1
        
c					WAVEFORM ONSET AND END DETERMINATION
		call p_significatius (ecgder,nqrs,iqrs,ifm,is,ns,f,ipbeg, 
     &		ippos1, ipend, iqbeg, iqpos, ispos, isend, itbeg, 
     &		itpos, itend, irpos, ecgpb, derfi, irrpos, iqend, isbeg,
     &		rrmed, ecg, deri, itpos2, morf, idis, nep) 

 	             	   
c	         do i=1, 100000
c	           v(1)=nint(200*ecgpb(i)/10)
c	           ig=putvec(v)
c                end do
        
  
c	   write(6,*) ilastqrs, iqrs(1)+imu_an,iqrs(2)+imu_an,iqrs(3)+imu_an  

	 
                if (iqrs(1)+imu_an.gt.ilastqrs+0.4*ifm) then
	            iprimerqrs=1
		else if (iqrs(2)+imu_an.gt.ilastqrs+0.4*ifm) then
		    iprimerqrs=2
	        else if (iqrs(2)+imu_an.le.ilastqrs+0.4*ifm) then
		    iprimerqrs=3
                end if

		ii=wfdbquiet(1)

               do ie=iprimerqrs,nqrs-1
               if (ipbeg(ie).gt.0) 
     &              ii=putann(0,ipbeg(ie)+imu_an,39,0,ic,0,' ')    
               if (ippos1(ie).gt.0) 
     &             ii=putann(0,ippos1(ie)+imu_an,24,0,ic,0,' ')    
               if (ipend(ie).gt.0) 
     &             ii=putann(0,ipend(ie)+imu_an,40,0,ic,0,' ')    
               if (iqbeg(ie).gt.0) 
     &                ii=putann(0,iqbeg(ie)+imu_an,39,0,ic,1,' ')    
               if (iqrs(ie).gt.0) 
     &              ii=putann(0,iqrs(ie)+imu_an,iqrst(ie),0,ic,0,' ')    
               if (isend(ie).gt.0) 
     &              ii=putann(0,isend(ie)+imu_an,40,0,ic,1,' ')    
               if (itbeg(ie).gt.0) 
     &              ii=putann(0,itbeg(ie)+imu_an,39,0,ic,2,' ')    
               if (itpos2(ie).gt.0) 
     &          ii=putann(0,itpos2(ie)+imu_an,27,0,ic,morf(4,ie),' ')    
               if (itpos(ie).gt.0.and.itpos(ie).ne.itpos2(ie)) 
     &          ii=putann(0,itpos(ie)+imu_an,27,0,ic,morf(4,ie),' ')    
               if (itend(ie).gt.0) 
     &              ii=putann(0,itend(ie)+imu_an,40,0,ic,2,' ')    
               end do
	       ii=wfdbverbose(1)
 	       ilastqrs=iqrs(nqrs-1)+imu_an
               imu_an=imu_an+100000-2*ifm 
	       write(6,*) '.. ',nqrs-iprimerqrs,' beats'
	       if (flag_qrs.eq.1.and.ij.eq.-1) go to 30
            end do

            close(unit=2) 
            close(unit=3) 
            close(unit=4) 
            close(unit=7) 
            close(unit=8) 
            close(unit=9)
c 	         i=newheader('pb')
	
 30 	    ii=wfdbquit(i)
         stop 
        end

                             
 
      subroutine help(i)

      write(6,*) 'usage: ecgpuwave -r RECORD -a ANNOTATOR [OPTIONS ...]'
      write(6,*) 'where RECORD specifies the input, ANNOTATOR is the'
      write(6,*) 'output annotator name, and OPTIONS may include:'
      write(6,*) ' -f TIME    start at specified TIME'
      write(6,*) ' -i IANN    read QRS detections from IANN'
      write(6,*) ' -n PFLAG   specify beats to process (requires -i):'
      write(6,*) '             all (PFLAG=0; default)'
      write(6,*) '             normal beats only (PFLAG=1)'
      write(6,*) ' -s SIGNAL  analyze the specified SIGNAL (default: 0)'
      write(6,*) ' -t TIME    stop at specified TIME'
      return
      end