--- /dev/null
+c===========================================================================
+c
+c This file is part of TISEAN
+c
+c Copyright (c) 1998-2007 Rainer Hegger, Holger Kantz, Thomas Schreiber
+c
+c TISEAN is free software; you can redistribute it and/or modify
+c it under the terms of the GNU General Public License as published by
+c the Free Software Foundation; either version 2 of the License, or
+c (at your option) any later version.
+c
+c TISEAN is distributed in the hope that it will be useful,
+c but WITHOUT ANY WARRANTY; without even the implied warranty of
+c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+c GNU General Public License for more details.
+c
+c You should have received a copy of the GNU General Public License
+c along with TISEAN; if not, write to the Free Software
+c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+c
+c===========================================================================
+c cross-recurrence plot
+c authors H. Kantz & T. Schreiber (2004)
+c modified by H. Kantz Feb 2007 (multivariate version)
+ program xrecur
+ parameter(nx=1000000,me=30,meps=1000,mx=10,nx1=10000000)
+ dimension x(nx,mx), y(nx,mx)
+ dimension x1(nx1),y1(nx1)
+ integer mlist(2), inot(nx1), icol(mx)
+ character*72 file1, file2, fout
+ data eps/1e-3/, id0/1/
+ data iverb/1/, xperc/100./
+
+ call whatido(
+ ."cross recurrence plot of two scalar or vector valued data sets"
+ . ,iverb)
+
+c ================================================================
+c assume two input files (file1, file2)
+c - with identical structure in terms of colums
+c - with identical embedding spaces
+c - with individual length and exclusions: l1,l2, x1,x2
+c - univariate data: maximum time series length nx1
+c - multivariate data: maximum length nx, maximum dimension mx
+c
+c either: fixed epsilon, plot certain percentage of all
+c neighbours found
+c or: fix the numbers of points of the y time series to be
+c found as neighbours of the x time series: non-symmetric!
+c norm: max-norm after rescaling of the individual components
+c unless rescaling is switched off
+c
+c=================================================================
+
+ id=ican("d",id0)
+
+ mmax=2
+ mdim=1
+
+ call imcan("m",2,mc,mlist)
+ if (mc.ge.2) then
+ mmax=mlist(2)
+ mdim=mlist(1)
+ if (mc.gt.2) print*,'extra arguments of -m ignored'
+ endif
+ ntmin=0
+ kmin=ican("k",0)
+ idown1=ican("s",1)
+ idown2=ican("S",1)
+ eps=fcan("r",eps)
+ xperc=fcan("%",xperc)
+ nmaxx=ican("l",nx)
+ nmaxy=ican("L",nx)
+ nexcl1=ican("x",0)
+ nexcl2=ican("X",0)
+ iscal=0
+ iscal=lopt("n",1)
+
+ call columns(mc,mx,icol)
+ if (mc.gt.0.and.mc.ne.mdim) stop 'improper number of columns'
+ isout=igetout(fout,0)
+ if(fout.eq." ") isout=1
+c
+ call nthstring(1,file1)
+ if(file1.eq."-") stop 'missing input filename'
+ if (mdim.gt.1)
+ . call xreadfile(nmaxx,mdim,nx,x,nexcl1,icol,file1,iverb)
+ if (mdim.eq.1)
+ . call xreadfile(nmaxx,1,nx1,x1,nexcl1,icol,file1,iverb)
+c
+ call nthstring(2,file2)
+ if(file2.eq."-") stop 'missing second input filename'
+ if (mdim.gt.1)
+ . call xreadfile(nmaxy,mdim,nx,y,nexcl2,icol,file2,iverb)
+ if (mdim.eq.1)
+ . call xreadfile(nmaxy,1,nx1,y1,nexcl2,icol,file2,iverb)
+
+ if(isout.eq.1) then
+ call addsuff(fout,file1,"_")
+ call addsuff(fout,fout,file2)
+ call addsuff(fout,fout,"_xrec")
+ endif
+
+c rescale data if flag -n is not set (iscal=1)
+ if (iscal.ne.1) then
+ print*,'normalizing data to unit interval'
+
+ if (mdim.gt.1) then
+
+c rescaling each component of file 1
+ do imx=1,mdim
+ xmin=x(1,imx)
+ xmax=x(1,imx)
+ do i1=2,nmaxx
+ xmax=max(xmax,x(i1,imx))
+ xmin=min(xmin,x(i1,imx))
+ enddo
+ scal=.9999d0/(xmax-xmin)
+ do i1=1,nmaxx
+ x(i1,imx)=(x(i1,imx)-xmin)*scal
+ enddo
+ enddo
+
+c rescaling each component of file 2
+
+ do imx=1,mdim
+ xmin=y(1,imx)
+ xmax=y(1,imx)
+ do i1=2,nmaxy
+ xmax=max(xmax,y(i1,imx))
+ xmin=min(xmin,y(i1,imx))
+ enddo
+ scal=.9999d0/(xmax-xmin)
+ do i1=1,nmaxy
+ y(i1,imx)=(y(i1,imx)-xmin)*scal
+ enddo
+ enddo
+
+ else
+
+c rescaling the single component of file 1
+ xmin=x1(1)
+ xmax=x1(1)
+ do i1=2,nmaxx
+ xmax=max(xmax,x1(i1))
+ xmin=min(xmin,x1(i1))
+ enddo
+ scal=.9999d0/(xmax-xmin)
+ do i1=1,nmaxx
+ x1(i1)=(x1(i1)-xmin)*scal
+ enddo
+
+c rescaling the single component of file 2
+
+ xmin=y1(1)
+ xmax=y1(1)
+ do i1=2,nmaxy
+ xmax=max(xmax,y1(i1))
+ xmin=min(xmin,y1(i1))
+ enddo
+ scal=.9999d0/(xmax-xmin)
+ do i1=1,nmaxy
+ y1(i1)=(y1(i1)-xmin)*scal
+ enddo
+
+ endif
+ endif
+
+ call outfile(fout,iunit,1)
+ ntot=0
+
+ if (kmin.eq.0) then
+c search all neighbours with distance < eps
+
+ xperc=xperc/100.
+
+ if (mdim.eq.1) then
+ call crossrec(nmaxx,x1,nmaxy,y1,eps,
+ . id,mmax,iunit,xperc,ntot,idown1,idown2)
+ else
+ call mcrossrec(nmaxx,x,nmaxy,y,eps,
+ . id,mmax,mdim,iunit,xperc,ntot,idown1,idown2)
+ endif
+
+c>-----------------------------------------------------------
+ else
+
+ do i=(mmax-1)*id+1,nmaxx
+ inot(i)=1
+ enddo
+ epsfac=1.1
+ eps=eps/epsfac
+
+ do 10 io=1,100
+ eps=eps*epsfac
+ if (mdim.eq.1) then
+ call crossrec1(nmaxx,x1,nmaxy,y1,eps,
+ . id,mmax,kmin,iunit,inot,ntodo,ntot,idown1,idown2)
+ else
+ call mcrossrec1(nmaxx,x,nmaxy,y,eps,id,mmax,mdim,kmin,iunit,
+ . inot,ntodo,ntot,idown1,idown2)
+ endif
+ if (iverb.eq.1) print*,eps,ntodo,ntot
+ if (ntodo.eq.0) goto 7
+ 10 continue
+c>--------------------------------------------------------
+ endif
+
+ 7 close(iunit)
+ print*,ntot,' points contained in the recurrence plot'
+ if (kmin.gt.0) print*,'last epsilon:',eps
+ if (kmin.gt.0) print*,'average number of neighbours:',
+ . real(ntot)*idown1/nmaxx
+ if (kmin.eq.0) print*,'using eps=',eps
+ end
+c========================================================
+ subroutine usage()
+c usage message
+
+ call whatineed(
+ ."[ -m#,# -d# -r# -k# -o outfile -l# -x# -L# -X# -c#[,#] -%# -V#
+ . -n -h] file1 file2")
+ call popt("m","# of components, embedding dimension [1,2]")
+ call popt("c","columns to be read [1,2,3,...,# of components]")
+ call popt("d","delay [1]")
+ call popt("r",
+ ."diameter of the neighbourhood as absolute value [.001]")
+ call popt("k",
+ ."find the # closest points, starting with diameter r")
+ call popt("%",
+ ."print only percentage of dots [100], no effect if -k is set")
+ call popt("l","length of time series 1 to be read [all data]")
+ call popt("x","# of initial lines in 1 to be skipped [0]")
+ call popt("s","use only every # delay vector of file 1 [1]")
+ call popt("L","length of time series 2 to be read [all data]")
+ call popt("X","# of initial lines in 2 to be skipped [0]")
+ call popt("S","use only every # delay vector of file 2 [1]")
+ call popt("n","if set: do NOT normalize data to unit interval")
+ call pout("file1_file2_xrec")
+ call pall()
+ stop
+ end
+c>--------------------------------------------------------------------
+ subroutine crossrec(nmaxx,x,nmaxy,y,eps,
+ . id,m,iunit,xperc,ntot,idown1,idown2)
+ parameter(im=100,ii=100000000,nx=1000000)
+ dimension y(nx),x(nx)
+ dimension jh(0:im*im),jpntr(nx),nlist(nx)
+ nseed=13413241
+
+ if(nmaxx.gt.nx.or.nmaxy.gt.nx) stop "crossrec: make nx larger."
+ mb=min(m,2)
+
+ call base(nmaxy,y,id,mb,jh,jpntr,eps)
+ nnull=(m-1)*id+1
+ do 20 n=nnull,nmaxx,idown1
+ call neigh(nx,x,y,n,nx,id,mb,jh,jpntr,eps,nlist,nfound)
+ do 30 nn=1,nfound ! all neighbours in two dimensions
+ np=nlist(nn)
+ if (np.lt.nnull) goto 30
+ if (mod(np-nnull,idown2).ne.0) goto 30
+ do 40 i=mb,m-1
+ if(abs(x(n-i*id)-y(np-i*id)).ge.eps) goto 30
+ 40 continue
+ call random(nseed,rr)
+ if (rr.le.xperc) write(iunit,*)n,np
+ if (rr.le.xperc) ntot=ntot+1
+ 30 continue
+ 20 continue
+ end
+c>--------------------------------------------------------------------
+ subroutine mcrossrec(nmaxx,x,nmaxy,y,eps,
+ . id,m,mdim,iunit,xperc,ntot,idown1,idown2)
+ parameter(im=100,nx=1000000,mx=10)
+ dimension y(nx,mx),x(nx,mx)
+ dimension jh(0:im*im),jpntr(nx),nlist(nx)
+ dimension vx(mx)
+ nseed=134512331
+
+ if(nmaxx.gt.nx.or.nmaxy.gt.nx) stop "mcrossrec: make nx larger."
+
+ call mbase(nmaxy,mdim,nx,y,id,1,jh,jpntr,eps)
+ nnull=(m-1)*id+1
+ do 20 n=nnull,nmaxx,idown1
+ do ii=1,mdim
+ vx(ii)=x(n,ii)
+ enddo
+ call mneigh2(nmaxy,mdim,y,nx,vx,jh,jpntr,eps,nlist,nfound)
+ do 30 nn=1,nfound ! all neighbours in mdim dimensions
+ np=nlist(nn)
+ if (np.lt.nnull) goto 30
+ if (mod(np-nnull,idown2).ne.0) goto 30
+ do 40 i=1,m-1
+ do 41 iim=1,mdim
+ if(abs(x(n-i*id,iim)-y(np-i*id,iim)).ge.eps) goto 30
+ 41 continue
+ 40 continue
+ call random(nseed,rr)
+ if (rr.le.xperc) write(iunit,*)n,np
+ if (rr.le.xperc) ntot=ntot+1
+ 30 continue
+ 20 continue
+ return
+ end
+
+ subroutine crossrec1(nmaxx,x,nmaxy,y,eps,id,m,kmin,iunit,
+ . inot,ntodo,ntot,idown1,idown2)
+ parameter(im=100,ii=100000000,nx=1000000)
+ dimension y(nmaxy),x(nmaxx),inot(nmaxx)
+ dimension jh(0:im*im),jpntr(nx),nlist(nx)
+ ntodo=0
+
+ if(nmaxx.gt.nx.or.nmaxy.gt.nx) stop "crossrec1: make nx larger."
+ mb=min(m,2)
+
+ call base(nmaxy,y,id,mb,jh,jpntr,eps)
+ nnull=(m-1)*id+1
+ do 20 n=nnull,nmaxx,idown1
+ if (inot(n).eq.0) goto 20
+ ntodo=ntodo+1
+ call neigh(nx,x,y,n,nx,id,mb,jh,jpntr,eps,nlist,nfound)
+ if (nfound.lt.kmin) goto 20
+ nreal=0
+ do 30 nn=1,nfound ! all neighbours in two dimensions
+ np=nlist(nn)
+ if(np.lt.nnull) goto 30
+ if (mod(np-nnull,idown2).ne.0) goto 30
+ do 40 i=mb,m-1
+ if(abs(x(n-i*id)-y(np-i*id)).ge.eps) goto 30
+ 40 continue
+ nreal=nreal+1
+ nlist(nreal)=np
+ 30 continue
+ if (nreal.lt.kmin) goto 20
+ ntodo=ntodo-1
+ inot(n)=0
+ ntot=ntot+nreal
+ do in=1,nreal
+ write(iunit,*)n,nlist(in)
+ enddo
+ 20 continue
+ end
+c>--------------------------------------------------------------------
+ subroutine mcrossrec1(nmaxx,x,nmaxy,y,eps,
+ . id,m,mdim,kmin,iunit,inot,
+ . ntodo,ntot,idown1,idown2)
+ parameter(im=100,nx=1000000,mx=10)
+ dimension y(nx,mx),x(nx,mx),inot(nmaxx)
+ dimension jh(0:im*im),jpntr(nx),nlist(nx)
+ dimension vx(mx)
+ ntodo=0
+
+ if(nmaxx.gt.nx.or.nmaxy.gt.nx) stop "mcrossrec1: make nx larger."
+
+ call mbase(nmaxy,mdim,nx,y,id,1,jh,jpntr,eps)
+ nnull=(m-1)*id+1
+ do 20 n=nnull,nmaxx,idown1
+ if (inot(n).eq.0) goto 20
+ ntodo=ntodo+1
+ do ii=1,mdim
+ vx(ii)=x(n,ii)
+ enddo
+ call mneigh2(nmaxy,mdim,y,nx,vx,jh,jpntr,eps,nlist,nfound)
+ if (nfound.lt.kmin) goto 20
+ nreal=0
+ do 30 nn=1,nfound ! all neighbours in mdim dimensions
+ np=nlist(nn)
+ if(np.lt.nnull) goto 30
+ if (mod(np-nnull,idown2).ne.0) goto 30
+ do 40 i=0,m-1
+ do 41 iim=1,mdim
+ if(abs(x(n-i*id,iim)-y(np-i*id,iim)).ge.eps) goto 30
+ 41 continue
+ 40 continue
+ nreal=nreal+1
+ nlist(nreal)=np
+ 30 continue
+ if (nreal.lt.kmin) goto 20
+ inot(n)=0
+ ntot=ntot+nreal
+ do in=1,nreal
+ write(iunit,*)n,nlist(in)
+ enddo
+ ntodo=ntodo-1
+ 20 continue
+ return
+ end
+
+ subroutine random(iseed,s)
+c
+c random number generator of Park & Miller
+ integer*8 ifac,ibase,iargument
+ ifac=7**5
+ ibase=2**30-1
+ im=im+2**30
+ iargument=iseed
+ iargument=mod(iargument*ifac,ibase)
+ s=float(iargument)/float(ibase)
+ iseed=iargument
+ return
+ end
+c>------------------------------------