c subroutine hires(ta,tai,el,nwin,nf,ares) real*8 el dimension ta(16400,1),tai(16400,1),el(1),ares(1) do j=1,nf ares(j)=0. end do do i=1,nwin a=1./(el(i)*nwin) do j=1,nf ares(j)=ares(j)+a*(ta(j,i)*ta(j,i)+tai(j,i)*tai(j,i)) end do end do do j=1,nf ares(j)=sqrt(ares(j)) end do return end c c subroutine adwait(ta,tai,dcf,el,nwin,nf,ares,degf,avar) c c this version uses Thomson's algorithm for calculating c the adaptive spectrum estimate c real*8 avar,spw,as,das,tol,el,a1,bias,scale,ax,fn,fx dimension ta(16400,1),tai(16400,1),el(1),ares(1),degf(1) dimension spw(10),bias(10),dcf(16400,1) c c set tolerance for iterative scheme exit c tol=3.d-4 jitter=0 scale=avar c c we scale the bias by the total variance of the frequency transform c from zero freq to the nyquist c in this application we scale the eigenspectra by the bias in order to avoid c possible floating point overflow c do 200 i=1,nwin 200 bias(i)=(1.d0-el(i)) do 100 j=1,nf do 150 i=1,nwin 150 spw(i)=(ta(j,i)*ta(j,i)+tai(j,i)*tai(j,i))/scale c c first guess is the average of the two lowest-order eigenspectral estimates c as=(spw(1)+spw(2))/2.d0 do 300 k=1,20 c c find coefficients c fn=0.d0 fx=0.d0 do 350 i=1,nwin a1=dsqrt(el(i))*as/(el(i)*as+bias(i)) a1=a1*a1 fn=fn+a1*spw(i) fx=fx+a1 350 continue ax=fn/fx das=dabs(ax-as) if(das/as.lt.tol) go to 400 300 as=ax c c flag if iteration does not converge c jitter=jitter+1 400 continue ares(j)=as*scale c c calculate degrees of freedom c df=0. do 450 i=1,nwin dcf(j,i)=dsqrt(el(i))*as/(el(i)*as+bias(i)) 450 df=df+dcf(j,i)*dcf(j,i) c c we normalize degrees of freedom by the weight of the first eigenspectrum c this way we never have fewer than two degrees of freedom c 100 degf(j)=df*2./(dcf(j,1)*dcf(j,1)) return end c subroutine regre(sr,si,nf,nwin,amu) c real b real *8 junk dimension sr(16400,1),si(16400,1),amu(16400,1) common/tapsum/b(10),junk(10) c c "b" is the DFT of Slepian eigentapers at zero frequency c "sr" and "si" are the eigenspectra c "amu" contains line frequency estimates and f-test parameter c sum=0. do i=1,nwin sum=sum+b(i)*b(i) end do do i=1,nf amu(i,1)=0. amu(i,2)=0. do j=1,nwin amu(i,1)=amu(i,1)+sr(i,j)*b(j) amu(i,2)=amu(i,2)+si(i,j)*b(j) end do amu(i,1)=amu(i,1)/sum amu(i,2)=amu(i,2)/sum sum2=0. do j=1,nwin sumr=sr(i,j)-amu(i,1)*b(j) sumi=si(i,j)-amu(i,2)*b(j) sum2=sum2+sumr*sumr+sumi*sumi end do amu(i,3)=(nwin-1)*(amu(i,2)**2+amu(i,1)**2)*sum/sum2 end do return end c c subroutine taper2(n,nwin,el) c c generate slepian tapers c "ta" is a real*4 array c c written by J. Park c real*8 el,a,z,pi,ww,cs,ai,an,eps,rlu,rlb real*8 dfac,drat,gamma,bh,ell real dump common/npiprol/anpi common/tapsum/tapsum(10),ell(10) common/misc/npad common/work/ip(32800) common/taperz/z(65536),dump(393728) common/stap2/ta(32800,16) dimension a(32800,8),el(10) data pi/3.14159265358979d0/ equivalence (a(1,1),ta(1,1)) an=dfloat(n) ww=dble(anpi)/an cs=dcos(2.d0*pi*ww) c c note: c c initialize matrix for eispack subroutine c this matrix is not the bandwidth retention factor matrix A (for minimizing c spectral leakage) described in various multitaper papers c --e.g. Thomson (1982) [proc ieee], Park et al (1987) [jgr]. c the bandwidth matrix x returns a cluster of eigenvectors c (which are the slepian tapers) with eigenvalues very close to unity. c since the spacing of eigenvalues can be comparable to machine precision, c numerical instability can occur for time-bandwidth product n .ge. 6 c (that is, 6pi-prolate tapers) c also, the bandwidth retention matrix A is toeplitz, but full, and it is not c feasible to calculate tapers explicitly for long time series (in an earlier c code i interpolated an m-point taper from the eigenvectors of a 128x128 c bandwidth retention matrix). the following is cribbed from a 1978 paper c by Slepian (Prolate spheroidal wave functions, Fourier analysis c and uncertainty, Bell System Tech Journal, v57, pp1371-1430, 1978) c which gives a three-term recursion that is satisfied by the c slepian tapers. the three-term recursion can be manipulated to show that the c slepian tapers are the eigenvectors of a tridiagonal matrix a, with c well-spaced eigenvalues that are (practically speaking) unrelated to the c eigenvalues of x. using this matrix a we obtain both numerical stability c and speed (tridiagonal matrices can be decomposed rapidly enough to c calculate m-point tapers on the fly). c do i=0,n-1 ai=dfloat(i) a(i+1,1)=-cs*((an-1.d0)/2.d0-ai)**2 a(i+1,2)=-ai*(an-ai)/2.d0 c c next statement is eispack routine tridib, see its documentation c a(i+1,3)=a(i+1,2)**2 end do eps=1.e-13 m11=1 call tridib(n,eps,a(1,1),a(1,2),a(1,3),rlb,rlu,m11,nwin,el,ip, x ierr,a(1,4),a(1,5)) call tinvit(n,n,a(1,1),a(1,2),a(1,3),nwin,el,ip,z,ierr, x a(1,4),a(1,5),a(1,6),a(1,7),a(1,8)) c c note: c c we calculate the eigenvalues of the dirichlet-kernel problem c i.e. the bandwidth retention factors c from slepian 1978 asymptotic formula, gotten from thomson 1982 eq 2.5 c supplemented by the asymptotic formula for k near 2n from Slepian (1978) c more precise values of these parameters, perhaps useful in adaptive c spectral estimation, can be calculated explicitly using the c rayleigh-quotient formulas in Thomson (1982) and Park et al (1987) c dfac=an*pi*ww drat=8.d0*dfac dfac=4.d0*dsqrt(pi*dfac)*dexp(-2.d0*dfac) do k=1,nwin el(k)=1.d0-dfac dfac=dfac*drat/k ! is this correct formula? yes,but fails as k -> 2n end do gamma=dlog(8.d0*an*dsin(2.d0*pi*ww))+0.5772156649d0 do k=1,nwin bh=-2.d0*pi*(an*ww-dfloat(k-1)/2.d0-.25d0)/gamma ell(k)=1.d0/(1.d0+dexp(pi*bh)) end do do i=1,nwin el(i)=dmax1(ell(i),el(i)) end do c c normalize the eigentapers to preserve power for a white process c i.e. they have rms value unity c "tapsum" is the average of the eigentaper, should be near zero for c antisymmetric tapers c do k=1,nwin kk=(k-1)*n tapsum(k)=0. tapsq=0. do i=1,n aa=z(kk+i) ta(i,k)=aa tapsum(k)=tapsum(k)+aa tapsq=tapsq+aa*aa end do aa=sqrt(tapsq/n) tapsum(k)=tapsum(k)/aa do i=1,n ta(i,k)=ta(i,k)/aa end do end do c c the real FFT will preserve amplitudes with zeropadding c for example, a(i)=1.,i=1,100 will transform at zero freq c to b(f=0)=100 no matter how much zero padding is done c therefore we need not doctor the taper normalization, c but wait until the fft to force the desired units c return end