ECGPUWAVE 1.3.4
(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