SYNOPSIS

PERL PROGRAM NAME:

AUTHOR: Juan Lorenzo (Perl module only)

DATE:

DESCRIPTION:

Version:

USE

NOTES

Examples

SYNOPSIS

SEISMIC UNIX NOTES SUKTMIG2D - prestack time migration of a common-offset

	section with the double-square root (DSR) operator	





   suktmig2d < infile vfile= [parameters]  > outfile		



 Required Parameters:						

 vfile=	rms velocity file (units/s) v(t,x) as a function

		of time						

 dx=		distance (units) between consecutive traces	



 Optional parameters:						

 fcdpdata=tr.cdp	first cdp in data			

 firstcdp=fcdpdata	first cdp number in velocity file	

 lastcdp=from header	last cdp number in velocity file	

 dcdp=from header	number of cdps between consecutive traces

 angmax=40	maximum aperture angle for migration (degrees)	

 hoffset=.5*tr.offset		half offset (m)			

 nfc=16	number of Fourier-coefficients to approximate	

		low-pass					

		filters. The larger nfc the narrower the filter	

 fwidth=5 	high-end frequency increment for the low-pass	

 		filters						

 		in Hz. The lower this number the more the number

		of lowpass filters to be calculated for each 	

		input trace.					



 Caveat: this code may need some work				

 Notes:							

 Data must be preprocessed with sufrac to correct for the	

 wave-shaping factor using phasefac=.25 for 2D migration.	



 Input traces must be sorted into offset and cdp number.	

 The velocity file consists of rms velocities for all CMPs as a

 function of vertical time and horizontal position v(t,x)	

 in C-style binary floating point numbers.  It's easiest to 	

 supply v(t,x) that has the same dimensions as the input data to

 be migrated. Note that time t is the fast dimension in these  

 the input velocity file.					



 The units may be feet or meters, as long as these are		

 consistent.							

 Antialias filter is performed using (Gray,1992, Geoph. Prosp), 

 using nc low- pass filtered copies of the data. The cutoff	

 frequencies are calculated  as fractions of the Nyquist	

 frequency.							



 The maximum allowed angle is 80 degrees(a 10 degree taper is 

 applied to the end of the aperture)				

define LOOKFAC 2 /* Look ahead factor for npfaro

define PFA_MAX 720720 /* Largest allowed nfft

Prototype of functions used internally

void lpfilt(int nfc, int nfft, float dt, float fhi, float *filter);

segy intrace; /* input traces

segy outtrace; /* migrated output traces

int

main(int argc, char **argv)

{

	int i,k,imp,iip,it,ix,ifc;	/* counters

	int ntr,nt;			/* x,t



	int verbose;	/* is verbose?				*/

	int nc;		/* number of low-pass filtered versions	*/

			/*  of the data for antialiasing	*/

	int nfft,nf;	/* number of frequencies		*/

	int nfc;	/* number of Fourier coefficients for low-pass filter

	int fwidth;	/* high-end frequency increment for the low-pass

			/* filters 				*/

	int firstcdp=0;	/* first cdp in velocity file		*/

	int lastcdp=0;	/* last cdp in velocity file		*/

	int oldcdp=0;	/* temporary storage			*/

	int fcdpdata=0;	/* first cdp in the data		*/

	int olddeltacdp=0;

	int deltacdp;

	int ncdp=0;	/* number of cdps in the velocity file	*/

	int dcdp=0;	/* number of cdps between consecutive traces



	float dx=0.0;	/* cdp sample interval

	float hoffset=0.0;  /* half receiver-source

	float p=0.0;	/* horizontal slowness of the migration operator

	float pmin=0.0;	/* maximum horizontal slowness for which there's

			/* no aliasing of the operator

	float dt;	/* t sample interval

	float h;	/* offset

	float x;	/* aperture distance

	float xmax=0.0;	/* maximum aperture distance



	float obliq;	/* obliquity factor

	float geoms;	/* geometrical spreading factor

	float angmax;   /* maximum aperture angle



	float mp,ip;	/* mid-point and image-point coordinates

	float t;	/* time

	float t0;	/* vertical traveltime

	float tmax;	/* maximum time



	float fnyq;	/* Nyquist frequency

	float ang;	/* aperture angle

	float angtaper=0.0;	/* aperture-angle taper

	float v;		/* velocity

  

	float *fc=NULL;		/* cut-frequencies for low-pass filters

	float *filter=NULL;	/* array of low-pass filter values



	float **vel=NULL;	/* array of velocity values from vfile

	float **data=NULL;	/* input data array*/

	float **lowpass=NULL;   /* low-pass filtered version of the trace

	float **mig=NULL;	/* output migrated data array



	register float *rtin=NULL,*rtout=NULL;/* real traces

	register complex *ct=NULL;   /* complex trace



	/* file names

	char *vfile="";		/* name of velocity file

	FILE *vfp=NULL;

	FILE *tracefp=NULL;	/* temp file to hold traces*/

	FILE *hfp=NULL;		/* temp file to hold trace headers



	float datalo[8], datahi[8];

	int itb, ite;

	float firstt, amplo, amphi;



	cwp_Bool check_cdp=cwp_false;	/* check cdp in velocity file	*/



	/* Hook up getpar to handle the parameters

	initargs(argc,argv);

	requestdoc(0);

	

	/* Get info from first trace

	if (!gettr(&intrace))  err("can't get first trace");

	nt=intrace.ns;

	dt=(float)intrace.dt/1000000;

	tmax=(nt-1)*dt;



	MUSTGETPARFLOAT("dx",&dx);

	MUSTGETPARSTRING("vfile",&vfile);

	if (!getparfloat("angmax",&angmax)) angmax=40;

	if (!getparint("firstcdp",&firstcdp)) firstcdp=intrace.cdp;

	if (!getparint("fcdpdata",&fcdpdata)) fcdpdata=intrace.cdp;

	if (!getparfloat("hoffset",&hoffset)) hoffset=.5*intrace.offset;

	if (!getparint("nfc",&nfc)) nfc=16;

	if (!getparint("fwidth",&fwidth)) fwidth=5;

	if (!getparint("verbose",&verbose)) verbose=0;



	h=hoffset;



	/* Store traces in tmpfile while getting a count of number of traces

	tracefp = etmpfile();

	hfp = etmpfile();

	ntr = 0;

	do {

		++ntr;



		/* get new deltacdp value

		deltacdp=intrace.cdp-oldcdp;



		/* read headers and data

		efwrite(&intrace,HDRBYTES, 1, hfp);

		efwrite(intrace.data, FSIZE, nt, tracefp);



		/* error trappings.

		/* ...did cdp value interval change?

		if ((ntr>3) && (olddeltacdp!=deltacdp)) {



			if (verbose) {

			warn("cdp interval changed in data");	

			warn("ntr=0 olddeltacdp=0 deltacdp=0"

				,ntr,olddeltacdp,deltacdp);

		 	check_cdp=cwp_true;

			}

		}

		

		/* save cdp and deltacdp values

		oldcdp=intrace.cdp;

		olddeltacdp=deltacdp;



	} while (gettr(&intrace));



	/* get last cdp  and dcdp

	if (!getparint("lastcdp",&lastcdp)) lastcdp=intrace.cdp; 

	if (!getparint("dcdp",&dcdp))	dcdp=deltacdp - 1;





	checkpars();



	/* error trappings

	if ( (firstcdp==lastcdp) 

		|| (dcdp==0) 

		|| (check_cdp==cwp_true) ) warn("Check cdp values in data!");



	/* rewind trace file pointer and header file pointer

	erewind(tracefp);

	erewind(hfp);



	/* total number of cdp's in data

	ncdp=lastcdp-firstcdp+1;



	/* Set up FFT parameters

	nfft = npfaro(nt, LOOKFAC*nt);

	if(nfft>= SU_NFLTS || nfft >= PFA_MAX)

	  err("Padded nt=0 -- too big",nfft);

	nf = nfft/2 + 1;



	/* Determine number of filters for antialiasing

	fnyq= 1.0/(2*dt);

	nc=ceil(fnyq/fwidth);

	if (verbose)

		warn(" The number of filters for antialiasing is nc= 0",nc);



	/* Allocate space

	data = alloc2float(nt,ntr);

	lowpass=alloc2float(nt,nc+1);

	mig=   alloc2float(nt,ntr);

	vel=   alloc2float(nt,ncdp);

	fc = alloc1float(nc+1);

	rtin= ealloc1float(nfft);

	rtout= ealloc1float(nfft);

	ct= ealloc1complex(nf);

	filter= alloc1float(nf);



	/* Read data from temporal array

	for (ix=0; ix<ntr; ++ix){

		efread(data[ix],FSIZE,nt,tracefp);

	}



	/* read velocities

	vfp=efopen(vfile,"r");

	efread(vel[0],FSIZE,nt*ncdp,vfp);

	efclose(vfp);



	/* Zero all arrays

	memset((void *) mig[0], 0,nt*ntr*FSIZE);

	memset((void *) rtin, 0, nfft*FSIZE);

	memset((void *) filter, 0, nf*FSIZE);

	memset((void *) lowpass[0], 0,nt*(nc+1)*FSIZE);



	/* Calculate cut frequencies for low-pass filters

	for(i=1; i<nc+1; ++i){

		fc[i]= fnyq*i/nc;

	}



	/* Start the migration process

	/* Loop over input mid-points first

	if (verbose) warn("Starting migration process...\n");

	for(imp=0; imp<ntr; ++imp){

		float perc;



		mp=imp*dx; 

		perc=imp*100.0/(ntr-1);

		if(fmod(imp*100,ntr-1)==0 && verbose)

			warn("migrated 0\n ",perc);



		/* Calculate low-pass filtered versions 

		/* of the data to be used for antialiasing

		for(it=0; it<nt; ++it){

			rtin[it]=data[imp][it];

		}

		for(ifc=1; ifc<nc+1; ++ifc){

			memset((void *) rtout, 0, nfft*FSIZE);

			memset((void *) ct, 0, nf*FSIZE);

			lpfilt(nfc,nfft,dt,fc[ifc],filter);

			pfarc(1,nfft,rtin,ct);



			for(it=0; it<nf; ++it){

				ct[it] = crmul(ct[it],filter[it]);

			}

			pfacr(-1,nfft,ct,rtout);

			for(it=0; it<nt; ++it){ 

				lowpass[ifc][it]= rtout[it]; 

			}

		}



		/* Loop over vertical traveltimes

		for(it=0; it<nt; ++it){

			int lx,ux;



			t0=it*dt;

			v=vel[imp*dcdp+fcdpdata-1][it];

			xmax=tan((angmax+10.0)*PI/180.0)*v*t0;

			lx=MAX(0,imp - ceil(xmax/dx)); 

			ux=MIN(ntr,imp + ceil(xmax/dx));

	

		/* loop over output image-points to the left of the midpoint

		for(iip=imp; iip>lx; --iip){

			float ts,tr;

			int fplo=0, fphi=0;

			float ref,wlo,whi;



			ip=iip*dx; 

			x=ip-mp; 

			ts=sqrt( pow(t0/2,2) + pow((x+h)/v,2) );

			tr=sqrt( pow(t0/2,2) + pow((h-x)/v,2) );

			t= ts + tr;

			if(t>=tmax) break;

			geoms=sqrt(1/(t*v));

	  		obliq=sqrt(.5*(1 + (t0*t0/(4*ts*tr)) 

					- (1/(ts*tr))*sqrt(ts*ts - t0*t0/4)*sqrt(tr*tr - t0*t0/4)));

	  		ang=180.0*fabs(acos(t0/t))/PI;  

	  		if(ang<=angmax) angtaper=1.0;

	  		if(ang>angmax) angtaper=cos((ang-angmax)*PI/20);

	  		/* Evaluate migration operator slowness p to determine

			/* the low-pass filtered trace for antialiasing

			pmin=1/(2*dx*fnyq);

			p=fabs((x+h)/(pow(v,2)*ts) + (x-h)/(pow(v,2)*tr));

				if(p>0){fplo=floor(nc*pmin/p);}

				if(p==0){fplo=nc;}

				ref=fmod(nc*pmin,p);

				wlo=1-ref;

				fphi=++fplo;

				whi=ref;

				itb=MAX(ceil(t/dt)-3,0);

				ite=MIN(itb+8,nt);

				firstt=(itb-1)*dt;

				/* Move energy from CMP to CIP

				if(fplo>=nc){

					for(k=itb; k<ite; ++k){

						datalo[k-itb]=lowpass[nc][k];

					}

					ints8r(8,dt,firstt,datalo,0.0,0.0,1,&t,&amplo);

					mig[iip][it] +=geoms*obliq*angtaper*amplo;

				} else if(fplo<nc){

					for(k=itb; k<ite; ++k){

						datalo[k-itb]=lowpass[fplo][k];

						datahi[k-itb]=lowpass[fphi][k];

					}

					ints8r(8,dt,firstt,datalo,0.0,0.0,1,&t,&amplo);

					ints8r(8,dt,firstt,datahi,0.0,0.0,1,&t,&amphi);

					mig[iip][it] += geoms*obliq*angtaper*(wlo*amplo + whi*amphi);

				}

			}



			/* loop over output image-points to the right of the midpoint

			for(iip=imp+1; iip<ux; ++iip){

				float ts,tr;

				int fplo=0, fphi;

				float ref,wlo,whi;



				ip=iip*dx; 

				x=ip-mp; 

				t0=it*dt;	  

				ts=sqrt( pow(t0/2,2) + pow((x+h)/v,2) );

				tr=sqrt( pow(t0/2,2) + pow((h-x)/v,2) );

				t= ts + tr;

				if(t>=tmax) break;

				geoms=sqrt(1/(t*v));

				obliq=sqrt(.5*(1 + (t0*t0/(4*ts*tr)) 

					- (1/(ts*tr))*sqrt(ts*ts 

						- t0*t0/4)*sqrt(tr*tr 

								- t0*t0/4)));

				ang=180.0*fabs(acos(t0/t))/PI;   

				if(ang<=angmax) angtaper=1.0;

				if(ang>angmax) angtaper=cos((ang-angmax)*PI/20.0);



				/* Evaluate migration operator slowness p to determine the 

				/* low-pass filtered trace for antialiasing

				pmin=1/(2*dx*fnyq);

				p=fabs((x+h)/(pow(v,2)*ts) + (x-h)/(pow(v,2)*tr));

				if(p>0){

					fplo=floor(nc*pmin/p);

				}

				if(p==0){

					fplo=nc;

				}



				ref=fmod(nc*pmin,p);

				wlo=1-ref;

				fphi=fplo+1;

				whi=ref;

				itb=MAX(ceil(t/dt)-3,0);

				ite=MIN(itb+8,nt);

				firstt=(itb-1)*dt;



				/* Move energy from CMP to CIP

				if(fplo>=nc){

					for(k=itb; k<ite; ++k){

						datalo[k-itb]=lowpass[nc][k];

					}

					ints8r(8,dt,firstt,datalo,0.0,0.0,1,&t,&amplo);

					mig[iip][it] +=geoms*obliq*angtaper*amplo;

				} else if(fplo<nc){

					for(k=itb; k<ite; ++k){

						datalo[k-itb]=lowpass[fplo][k];

						datahi[k-itb]=lowpass[fphi][k];

					}

					ints8r(8,dt,firstt,datalo,0.0,0.0,1,&t,&amplo);

					ints8r(8,dt,firstt,datahi,0.0,0.0,1,&t,&amphi);

					mig[iip][it] += geoms*obliq*angtaper*(wlo*amplo + whi*amphi);

				}

			}



		}

	} 



	/* Output migrated data

	erewind(hfp);

	for (ix=0; ix<ntr; ++ix) {

		efread(&outtrace, HDRBYTES, 1, hfp);

		for (it=0; it<nt; ++it) {

			outtrace.data[it] = mig[ix][it];

		}

		puttr(&outtrace);

	}



	efclose(hfp);



	return(CWP_Exit());

}

void

lpfilt(int nfc, int nfft, float dt, float fhi, float *filter)

lpfilt -- low-pass filter using Lanczos Smoothing

(R.W. Hamming:"Digital Filtering",1977)

Input:

nfc number of Fourier coefficients to approximate ideal filter

nfft number of points in the fft

dt time sampling interval

fhi cut-frequency

Output:

filter array[nf] of filter values

Notes: Filter is to be applied in the frequency domain

Author: CWP: Carlos Pacheco 2006

{

int i,j;  /* counters

int nf;   /* Number of frequencies (including Nyquist)

float onfft;  /* reciprocal of nfft

float fn; /* Nyquist frequency

float df; /* frequency interval

float dw; /* frequency interval in radians

float whi;/* cut-frequency in radians

float w;  /* radian frequency



nf= nfft/2 + 1;

onfft=1.0/nfft;

fn=1.0/(2*dt);

df=onfft/dt;

whi=fhi*PI/fn;

dw=df*PI/fn;



for(i=0; i<nf; ++i){

	filter[i]= whi/PI;

	w=i*dw;



	for(j=1; j<nfc; ++j){

		float c= sin(whi*j)*sin(PI*j/nfc)*2*nfc/(PI*PI*j*j);

		filter[i] +=c*cos(j*w);

	}

}

}

User's notes (Juan Lorenzo) untested

CHANGES and their DATES

Import packages

instantiation of packages

Encapsulated hash of private variables

sub Step

collects switches and assembles bash instructions by adding the program name

sub note

collects switches and assembles bash instructions by adding the program name

sub clear

sub ang

sub angmax

sub angtaper

sub c

sub check_cdp

sub ct

sub data

sub dcdp

sub deltacdp

sub df

sub dt

sub dw

sub dx

sub fc

sub fcdpdata

sub filter

sub firstcdp

sub firstt

sub fn

sub fnyq

sub fphi

sub fplo

sub fwidth

sub geoms

sub h

sub hfp

sub hoffset

sub i

sub ifc

sub iip

sub imp

sub ip

sub it

sub itb

sub ite

sub ix

sub j

sub k

sub lastcdp

sub lowpass

sub lx

sub mig

sub mp

sub nc

sub ncdp

sub nf

sub nfc

sub nfft

sub nt

sub ntr

sub obliq

sub oldcdp

sub olddeltacdp

sub onfft

sub p

sub perc

sub phasefac

sub pmin

sub ref

sub rtin

sub rtout

sub t

sub t0

sub tmax

sub tr

sub tracefp

sub ts

sub ux

sub v

sub vel

sub verbose

sub vfile

sub vfp

sub w

sub whi

sub wlo

sub x

sub xmax

sub get_max_index

max index = number of input variables -1