ECGPUWAVE 1.3.4

File: <base>/src/ecgpuwave/int_qt.f (15,816 bytes)
c
c        ----------------------------------------------------------------------
C          INT_QT.FOR BUSCA EL INICIO DE LA ONDA Q Y EL FIN DE LA T
C          PARA MEDIR EL QT
C           AUTOR: PABLO LAGUNA
C           FECHA: 17-9-87
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        Se llama desde ecgmain 

C        ----------------------------------------------------------------------
C           BUSCA EL INTERVALO QT
C        ----------------------------------------------------------------------

         subroutine int_qt(sen,der1,iqrs,iondaq,iondat,ifm,nqrs,
     &                     iqt,iqtc,iask)

         dimension sen(100000),der1(100000),iqrs(8000),iondaq(8000)
         dimension iqt(8000),iqtc(8000),iondat(8000)
                        
         if (iask.eq.2) then
          write(6,*)
          write(6,*) 'que fraccion quieres de la derivada?'
 5        write(6,10)
 10       format('$ der_limite = der_maxima / x    x= ')
          read(6,*,err=5) frac 
         end if
         
         call frec_cardiaca(ifm,iqrs,nqrs,irrint)
         J=0
  
         
          do i=1,nqrs
           call busca_q(sen,der1,iqrs(i),iondaq(i),ifm)
           if (iask.eq.1) then  
             call busca_t1(sen,der1,iqrs(i),iondat(i),ifm,irrint)
                          else 
             call busca_t2(sen,der1,iqrs(i),iondat(i),ifm,irrint,frac) 
           end if
          iqt(i)=(iondat(i)-iondaq(i))*1000/ifm

          rr=(iqrs(i)-iqrs(i-1))/float(ifm)
          if (i.eq.1) rr=(iqrs(2)-iqrs(1))/float(ifm)
          call qt_corregido(rr,irrint,ifm,iqt(i),iqtc(i))    
          if (i.gt.2) call ajustrr(i,iqrs,irrint,no_uso)
         end do
         
         do i=nqrs+1,8000
          iqt(i)=0
          iondaq(i)=0
          iondat(i)=0
          iqtc(i)=0
         end do

         return
         end
C        ----------------------------------------------------------------------
C           BUSCA EL INCIO DE LA ONDA Q
C        ----------------------------------------------------------------------

         subroutine busca_q(sen,der1,iqrs,iqb,ifm)          

         dimension sen(100000),der1(100000)
         dimension der2(8000),der1f(8000)

c        sen ES LA SEQAL EN LA QUE MIRO LA ONA Q
c        der1 ES SU DERIVADA PRIMERA
c        iqrs SON LAS POSICIONES LOS QRS DETECTADOS EN LA SEQAL sen
c        iondaq  SON LAS POSICIONES DEL INICIO DEL QRS
c        der2 ES LA DERIVADA SEGUNDA SE sen EN ZONAS QUE INTERESA 
c        ifm ES LA FRECUENCIA A LA QUE ESTA MUESTREADA LA SEQAL
C        nqrs ES EL NUMERO DE QRS QUE HAY SELECCIONADOS EN LA SEQAL
                    
         in=nint(ifm*0.04)
         n=iqrs
          if (sen(n).gt.0) then
                   call r_q(ifm,der1,iqrs,iq)             
                   ir=iqrs
                           else
                   call posimaxmin(der1,imaxd,imind,iqrs,iqrs+in)
                   call posimaxmin(der1,imaxi,imini,iqrs-in,iqrs)
                   if (der1(imaxd).gt.(-der1(imini))) then
                                   call detectar_cero(der1,n,'d')
                                   ir=n
                                   iq=iqrs
                                                    else
                                   call detectar_cero(der1,n,'i')
                                   ir=n
                                   call r_q(ifm,der1,n,iq)
                   end if 
          end if

c         SI HAY Q BUSCO DONDE EMPIEZA: PRIMERO VEO DONDE ES MAS PENDIENTE
C         EL FLANCO DE BAJADA DE LA ONDA Q (j) Y LUEGO MIRO PARA ATRAS DONDE 
C         CAMBIA MAS RAPIDAMENTE LA DERIVADA-> MAXIMO DE LA DERIVADA 2 

          in=nint(ifm*0.04)
          if (iq.gt.0) then
                         j=iq
                         do while (der1(j-1).le.der1(j))
                          j=j-1
                         end do
                         call derivada2(j-in,j,der1,der2,ifm)
                         l=j                        
                         call detectar_cero(der1,l,'i')
                         k=in
                         call detectar_cero(der2,k,'i')
                         if (l.gt.j-(in-k)) then 
                                       iqb=l
                                            else
                                       iqb=j-(in-k)
                         end if  
                         if (iqb.lt.iq-ifm*0.06) iqb=iq
          
                       else
c                        PARTO HACIA ATRAS DE LA ONDA R POSITIVA  
                  call fpbc(ir-ifm/10,ifm/10,ifm,30,der1,der1f,ret_pb)
                         j=ifm/10
                         do while (der1f(j-1).ge.der1f(j))
                          j=j-1
                         end do
                         idermax=ir-ifm/10+j
                         call derivada2(j-in,j,der1f,der2,ifm)
                         l=idermax    
                         call detectar_cero(der1,l,'i')
                         k=in-1
                         call detectar_cero(der2,k,'i')
                         if (l.gt.idermax-(in-k)) then 
                                       iqb=l
                                     else
                                       iqb=idermax-(in-k)
                         end if   
                          
          end if
          
          return
          end 


c         ------------------------------------------------------------------
C             VA DE LA POSICON DE LA ONDA R A LA DE LA ONDA Q SI LA HAY
C         ------------------------------------------------------------------

          subroutine r_q(ifm,der1,ir,iq)
        
          dimension der1(100000)          

c             BUSCO LA POSICION DELA ONDA Q 'IQ' 40 MS.
C             ANTES DE LA ONDA R SI NO ESTA AQUI IQ=0

          n=ir
          call detectar_cero(der1,n,'i')
          in=nint(ifm*0.035)
          if (n.le.ir-in) then 
                           iq=0
                          else
                           iq=n
          end if
          return
          end

    

C         -------------------------------------------------------------------
C          CALCULA LA DERIVADA DEL TROZO DE SEQAL QUE MANDO
C         -------------------------------------------------------------------

          subroutine derivada2(ni,nf,x,y,ifm)

          dimension x(100000),y(8000)

c         ni,nf SON LOS PTOS. INICIAL Y FINAL DE LOS QUE CALCULO LA DERIVADA
C         EN X PONGO LA SEQAL DE ENTRADA Y EN Y LA DE SALIDA

          k=ifm/8
          y(1)=(ifm/4)*(x(ni+2)+2*x(ni+1)-3*x(ni))
          y(2)=(ifm/7)*(x(ni+3)+2*x(ni+2)-3*x(ni))
          do i=3,nf-ni
           y(i)=k*(x(ni+i+1)+2*x(ni+i)-2*x(ni+i-2)-x(ni+i-3))
          end do
          do i=nf-ni+1,8000
           y(i)=0
          end do
          
          return
          end


C         --------------------------------------------------------------------
C          DETECTA EL CERO SIGUIENTE DE LA SEQAL DE ENTRADA SEN A LA DERECHA
C          O LA IZQUIERDA 'I' 'D' Y SACA LAPOSICION EN N
C         --------------------------------------------------------------------

          subroutine detectar_cero(sen,n,sentido)
          
          dimension sen(100000)
          character*1 sentido

          if (sentido.eq.'i') then 
                               i=n-1
                               do while (sen(i)*sen(i-1).gt.0)
                                i=i-1
                               end do
                              else   
                               i=n+1
                               do while (sen(i)*sen(i-1).gt.0)
                                i=i+1
                               end do
          end if     
          n=i
          return
          end


C         --------------------------------------------------------------------
C          SACA LA POSICION DEL MAXIMO Y DEL MINIMO DE LA SEQAL
C         --------------------------------------------------------------------

          subroutine posimaxmin(sen,imax,imin,ni,nf)
          
          dimension sen(100000)
 
          imax=ni
          imin=ni
          do i=ni,nf
           if (sen(i).gt.sen(imax)) imax=i
           if (sen(i).lt.sen(imin)) imin=i
          end do
  
          return
          end



C        ----------------------------------------------------------------------
C           BUSCA EL FIN DE LA ONDA T SEGUN EL METODO DE LA DERIVADA SEGUNDA
C        ----------------------------------------------------------------------

         subroutine busca_t1(sen,der1,iqrs,ite,ifm,irrint)

         dimension sen(100000),der1(100000),der1f(8000)
         dimension der2(300)

c        sen eS LA SEQAL EN LA QUE MIRO LA ONA Q
c        der1f ES LA DERIVADA PRIMERA FILTRADA
c        der1 eS SU DERIVADA PRIMERA 
c        iqrs SON LAS POSICIONES LOS QRS DETECTADOS EN LA SEQAL sen
c        iondat  SON LAS POSICIONES DEL INICIO DEL QRS
c        der2 ES LA DERIVADA SEGUNDA DE sen EN ZONAS QUE INTERESA 
c        ifm ES LA FRECUENCIA A LA QUE ESTA MUESTREADA LA SEQAL
C        nqrs ES EL NUMERO DE QRS QUE HAY SELECCIONADOS EN LA SEQAL
c        IT ES LA POSICION DE LA ONDA t

         
         it=0
         call busca_it(ifm,irrint,sen,iqrs,der1,it)
c         BUSCO EL PUNTO SE MAYOR DERIVADA NEGATIVA ENTRE IT Y IT+100MS. 
          call fpbc(it,ifm/3,ifm,30,der1,der1f,ret_pb)
          call posimaxmin(der1,imax,j1,it,it+ifm/10)
          call posimaxmin(der1f,imax,j2,1,ifm/10)
          if (j1.gt.it+j2) then 
                         m=j1
                        else
                         m=it+j2
          end if
          
c         BUSCO EL FINAL DE LA ONDA T
          in=nint(ifm*0.2)
          call derivada2(m-it,m-it+in,der1f,der2,ifm)
          l=m
          call detectar_cero(der1,l,'d')
          k=2
          call detectar_cero(der2,k,'d')
          if (l.lt.m+k) then 
                         ite=l
                        else
                         ite=m+k
          end if
          
         return
         end          

C        ----------------------------------------------------------------------
C           BUSCA EL FIN DE LA ONDA T SEGUN EL METODO DEL % DE DERIVADA
C        ----------------------------------------------------------------------

         subroutine busca_t2(sen,der1,iqrs,ite,ifm,irrint,frac)

         dimension sen(100000),der1(100000)
         dimension der1F(8000)

c        sen eS LA SEQAL EN LA QUE MIRO LA ONA Q
c        der1 eS SU DERIVADA PRIMERA 
c        iqrs SON LAS POSICIONES LOS QRS DETECTADOS EN LA SEQAL sen
c        iondat  SON LAS POSICIONES DEL INICIO DEL QRS
c        der1f ES LA DERIVADA PRIMERA FILTRADA PASO BAJO
c        ifm ES LA FRECUENCIA A LA QUE ESTA MUESTREADA LA SEQAL
C        nqrs ES EL NUMERO DE QRS QUE HAY SELECCIONADOS EN LA SEQAL
c        IT ES LA POSICION DE LA ONDA t

         it=0
         call busca_it(ifm,irrint,sen,iqrs,der1,it)

c         BUSCO EL PUNTO SE MAYOR DERIVADA NEGATIVA ENTRE IT Y IT+100MS. 
          call fpbc(it,ifm/5,ifm,30,der1,der1f,ret_pb)
          call posimaxmin(der1f,imax,j2,1,ifm/10)
          derlim=der1f(j2)/frac
          
c         BUSCO EL FINAL DE LA ONDA T
          j=j2
          do while (der1f(j).lt.derlim)
           j=j+1
          end do
          ite=j+it
          if (i.gt.2) call ajustrr(i,iqrs,irrint,no_uso)
          
          
         return
         end          


C        ------------------------------------------------------------
C          BUSCA LA POSICION DE LA ONDA T
C        ------------------------------------------------------------

         subroutine busca_it(ifm,irrint,sen,iqr,der1,it)

         dimension sen(100000),der1(100000)

c        BUSCO LA ONDA t ENTRE 100 Y 400 MS. DESPUES DEL QRS
         ilim1=nint(ifm*0.1)
         if (irrint.lt.ifm*3/5) then 
                                 ilim2=nint(irrint/2.)
                               else
                                 ilim2=nint(ifm*0.4)
         end if  
         rmax=-abs(sen(iqr))
         j=iqr+ilim1
         do while (j.lt.iqr+ilim2)
           call detectar_cero(der1,j,'d')
           if (sen(j).gt.rmax) then
                                rmax=sen(j)
                                if (j.lt.iqr+ilim2) it=j
           end if
         end do
         if (it.lt.iqr) it=j
         return
         end


C        ------------------------------------------------------------
C         CALCULA EL QT CORREGIDO
C        ------------------------------------------------------------

         subroutine qt_corregido(rr,irrint,ifm,iqt,iqtc)

c         CALCULO EL QT CORREGIDO SI EL INTERVALO RR ESTA ACOTADO
      
          if (rr.lt.irrint*1.1/ifm.and.rr.gt.irrint*0.9/ifm) then
                                           iqtc=iqt/sqrt(rr)
          end if
          if (rr.lt.irrint*0.6/ifm) then 
                                  iqtc=0
          endif                               
      
          return
          end

C        -------------------------------------------------------------
C         BUSCA LA FRECUENCIA CARDIACA MEDIA
C        ------------------------------------------------------------

         subroutine frec_cardiaca(ifm,iqrs,nqrs,irrint)

         dimension iqrs(8000)

C        BUSCO LA FRECUENCIA DEL CORAZON MAS COMUN

         isum=0
         max=0
         min=iqrs(2)-iqrs(1)
         nqrsini=10
         if (nqrs.le.10) nqrsini=nqrs-1

         icon=0
         do i=1,nqrsini
          irrint=iqrs(i+1)-iqrs(i)
c         VEO SI LA FRECUENCIA CARDIACA ESTA EN (30,200)PULSACIONES/MIN.
          if (irrint.gt.ifm*3/10.and.irrint.lt.ifm*2) then
                if (irrint.gt.max) max=irrint
                if (irrint.lt.min) min=irrint
                isum=irrint+isum
                icon=icon+1 
          end if
         end do
         if (icon.gt.2) irrint=(isum-max-min)/(icon-2)
         return
         end


C        ----------------------------------------------------------------
C         CREA UN FICHERO CON LOS QT
C        ---------------------------------------------------------------

         subroutine escribe_qt(tit,ifm,iqt,nqrs)

         character*16  tit
         dimension iqt(8000)

c        CREA UN FICHERO NONDE GUARDA EL QT

         open(unit=1,file=tit,status='new')
         do i=1,nqrs
          write(1,*) iqt(i)*1000/ifm
         end do
         close(unit=1)       

         return
         end