int main(int argc, char **argv) { int nt; /* number of time samples per trace */ float dt; /* time sampling interval */ float ft; /* time of first sample */ int it; /* time sample index */ int ncdp; /* number of cdps specified */ float *cdp; /* array[ncdp] of cdps */ int icdp; /* index into cdp array */ int jcdp; /* index into cdp array */ int nvnmo; /* number of vnmos specified */ float *vnmo; /* array[nvnmo] of vnmos */ int ntnmo; /* number of tnmos specified */ float *tnmo; /* array[ntnmo] of tnmos */ float **ovv; /* array[ncdp][nt] of sloth (1/velocity^2) functions */ float *ovvt; /* array[nt] of sloth for a particular trace */ int nanis1; /* number of anis1's specified */ int nanis2; /* number of anis2's specified */ float *anis1; /* array[nanis1] of anis1's */ float *anis2; /* array[nanis2] of anis2's */ float **oa1; /* array[ncdp][nt] of anis1 functions */ float **oa2; /* array[ncdp][nt] of anis2 functions */ float *oa1t; /* array[nt] of anis1 for a particular trace */ float *oa2t; /* array[nt] of anis2 for a particular trace */ float smute; /* zero samples with NMO stretch exceeding smute */ float osmute; /* 1/smute */ int lmute; /* length in samples of linear ramp for mute */ int itmute=0; /* zero samples with indices less than itmute */ int sscale; /* if non-zero, apply NMO stretch scaling */ int invert; /* if non-zero, do inverse NMO */ float sy; /* cross-line offset component */ int ixoffset; /* indes for cross-line offset component */ long oldoffset; /* offset of previous trace */ long oldcdp; /* cdp of previous trace */ int newsloth; /* if non-zero, new sloth function was computed */ float tn; /* NMO time (time after NMO correction) */ float v; /* velocity */ float *qtn; /* NMO-corrected trace q(tn) */ float *ttn; /* time t(tn) for NMO */ float *atn; /* amplitude a(tn) for NMO */ float *qt; /* inverse NMO-corrected trace q(t) */ float *tnt; /* time tn(t) for inverse NMO */ float *at; /* amplitude a(t) for inverse NMO */ float acdp; /* temporary used to sort cdp array */ float *aovv; /* temporary used to sort ovv array */ float *aoa1; /* temporary used to sort oa1 array */ float *aoa2; /* temporary used to sort oa2 array */ float temp; /* temporary float */ float tsq; /* temporary float */ int i; /* index used in loop */ int upward; /* scans upward if it's nonzero. */ /* hook up getpar */ initargs(argc, argv); requestdoc(1); /* get information from the first header */ if (!gettr(&tr)) err("can't get first trace"); nt = tr.ns; dt = ((double) tr.dt)/1000000.0; ft = tr.delrt/1000.0; sy = tr.sy; /* get velocity functions, linearly interpolated in time */ ncdp = countparval("cdp"); if (ncdp>0) { if (countparname("vnmo")!=ncdp) err("a vnmo array must be specified for each cdp"); if (countparname("tnmo")!=ncdp) err("a tnmo array must be specified for each cdp"); if (countparname("anis1")!=ncdp && countparname("anis1")!=0) err("an anis1 array must be specified for each cdp, " "or omitted at all"); if (countparname("anis2")!=ncdp && countparname("anis2")!=0) err("an anis2 array must be specified for each cdp, " "or omitted at all"); } else { ncdp = 1; if (countparname("vnmo")>1) err("only one (or no) vnmo array must be specified"); if (countparname("tnmo")>1) err("only one (or no) tnmo array must be specified"); if (countparname("anis1")>1) err("only one (or no) anis1 array must be specified"); if (countparname("anis2")>1) err("only one (or no) anis2 array must be specified"); } cdp = ealloc1float(ncdp); if (!getparfloat("cdp",cdp)) cdp[0] = tr.cdp; ovv = ealloc2float(nt,ncdp); oa1 = ealloc2float(nt,ncdp); oa2 = ealloc2float(nt,ncdp); for (icdp=0; icdp<ncdp; ++icdp) { nvnmo = countnparval(icdp+1,"vnmo"); ntnmo = countnparval(icdp+1,"tnmo"); nanis1 = countnparval(icdp+1,"anis1"); nanis2 = countnparval(icdp+1,"anis2"); if (nvnmo!=ntnmo && !(ncdp==1 && nvnmo==1 && ntnmo==0)) err("number of vnmo and tnmo values must be equal"); if (nanis1!=nvnmo && nanis1 != 0) err("number of vnmo and anis1 values must be equal"); if (nanis2!=nvnmo && nanis2 != 0) err("number of vnmo and anis2 values must be equal"); if (nvnmo==0) nvnmo = 1; if (ntnmo==0) ntnmo = nvnmo; if (nanis1==0) nanis1 = nvnmo; if (nanis2==0) nanis2 = nvnmo; /* equal numbers of parameters vnmo, tnmo, anis1, anis2 */ vnmo = ealloc1float(nvnmo); tnmo = ealloc1float(nvnmo); anis1 = ealloc1float(nvnmo); anis2 = ealloc1float(nvnmo); if (!getnparfloat(icdp+1,"vnmo",vnmo)) vnmo[0] = 1500.0; if (!getnparfloat(icdp+1,"tnmo",tnmo)) tnmo[0] = 0.0; if (!getnparfloat(icdp+1,"anis1",anis1)) for (i=0; i<nvnmo; i++) anis1[i] = 0.0; if (!getnparfloat(icdp+1,"anis2",anis2)) for (i=0; i<nvnmo; i++) anis2[i] = 0.0; for (it=1; it<ntnmo; ++it) if (tnmo[it]<=tnmo[it-1]) err("tnmo values must increase monotonically"); for (it=0,tn=ft; it<nt; ++it,tn+=dt) { intlin(ntnmo,tnmo,vnmo,vnmo[0],vnmo[nvnmo-1],1,&tn,&v); ovv[icdp][it] = 1.0/(v*v); } for (it=0,tn=ft; it<nt; ++it,tn+=dt) { intlin(ntnmo,tnmo,anis1,anis1[0],anis1[nanis1-1],1,&tn, &oa1[icdp][it]); } for (it=0,tn=ft; it<nt; ++it,tn+=dt) { intlin(ntnmo,tnmo,anis2,anis2[0],anis2[nanis2-1],1,&tn, &oa2[icdp][it]); } free1float(vnmo); free1float(tnmo); free1float(anis1); free1float(anis2); } /* sort (by insertion) sloth and anis functions by increasing cdp */ for (jcdp=1; jcdp<ncdp; ++jcdp) { acdp = cdp[jcdp]; aovv = ovv[jcdp]; aoa1 = oa1[jcdp]; aoa2 = oa2[jcdp]; for (icdp=jcdp-1; icdp>=0 && cdp[icdp]>acdp; --icdp) { cdp[icdp+1] = cdp[icdp]; ovv[icdp+1] = ovv[icdp]; oa1[icdp+1] = oa1[icdp]; oa2[icdp+1] = oa2[icdp]; } cdp[icdp+1] = acdp; ovv[icdp+1] = aovv; oa1[icdp+1] = aoa1; oa2[icdp+1] = aoa2; } /* get other optional parameters */ if (!getparfloat("smute",&smute)) smute = 1.5; if (!getparint("ixoffset",&ixoffset)) ixoffset=0; if (ixoffset==0) sy = 0.0; if (smute<=0.0) err("smute must be greater than 0.0"); if (!getparint("lmute",&lmute)) lmute = 25; if (!getparint("sscale",&sscale)) sscale = 1; if (!getparint("invert",&invert)) invert = 0; if (!getparint("upward",&upward)) upward = 0; /* allocate workspace */ ovvt = ealloc1float(nt); oa1t = ealloc1float(nt); oa2t = ealloc1float(nt); ttn = ealloc1float(nt); atn = ealloc1float(nt); qtn = ealloc1float(nt); tnt = ealloc1float(nt); at = ealloc1float(nt); qt = ealloc1float(nt); /* interpolate sloth and anis function for first trace */ interpovv(nt,ncdp,cdp,ovv,oa1,oa2,(float)tr.cdp,ovvt,oa1t,oa2t); /* set old cdp and old offset for first trace */ oldcdp = tr.cdp; oldoffset = tr.offset-1; warn("sy = %f",sy); /* loop over traces */ do { /* if necessary, compute new sloth and anis function */ if (tr.cdp!=oldcdp && ncdp>1) { interpovv(nt,ncdp,cdp,ovv,oa1,oa2,(float)tr.cdp, ovvt,oa1t,oa2t); newsloth = 1; } else { newsloth = 0; } /* if sloth and anis function or offset has changed */ if (newsloth || tr.offset!=oldoffset) { /* compute time t(tn) (normalized) */ temp = ((float) tr.offset*(float) tr.offset + sy*sy)/(dt*dt); for (it=0,tn=ft/dt; it<nt; ++it,tn+=1.0) { tsq = temp*ovvt[it] + \ oa1t[it]*temp*temp / (1.0+oa2t[it]*temp); if (tsq<0.0) err("negative moveout; check anis1, " "anis2, or suwind far-offset " "traces"); if ((1.0+oa2t[it]*temp)<=0.0) err("anis2 negative and too small; " "check anis2, or suwind far-offset" " traces"); ttn[it] = sqrt (tn*tn + tsq); } /* compute inverse of stretch factor a(tn) */ atn[0] = ttn[1]-ttn[0]; for (it=1; it<nt; ++it) atn[it] = ttn[it]-ttn[it-1]; /* determine index of first sample to survive mute */ osmute = 1.0/smute; if( !upward ) { for (it=0; it<nt-1 && atn[it]<osmute; ++it) ; } else { /* scan samples from bottom to top */ for (it=nt-1; it>0 && atn[it]>=osmute; --it) ; } itmute = it; /* if inverse NMO will be performed */ if (invert) { /* compute tn(t) from t(tn) */ yxtoxy(nt-itmute,1.0,ft/dt+itmute,&ttn[itmute], nt-itmute,1.0,ft/dt+itmute, ft/dt-nt,ft/dt+nt,&tnt[itmute]); /* adjust mute time */ itmute = 1.0+ttn[itmute]-ft/dt; itmute = MIN(nt-2,itmute); /* compute a(t) */ if (sscale) { for (it=itmute+1; it<nt; ++it) at[it] = tnt[it]-tnt[it-1]; at[itmute] = at[itmute+1]; } } } /* if forward (not inverse) nmo */ if (!invert) { /* do nmo via 8-point sinc interpolation */ ints8r(nt,1.0,ft/dt,tr.data,0.0,0.0, nt-itmute,&ttn[itmute],&qtn[itmute]); /* apply mute */ for (it=0; it<itmute; ++it) qtn[it] = 0.0; /* apply linear ramp */ for (it=itmute; it<itmute+lmute && it<nt; ++it) qtn[it] *= (float)(it-itmute+1)/(float)lmute; /* if specified, scale by the NMO stretch factor */ if (sscale) for (it=itmute; it<nt; ++it) qtn[it] *= atn[it]; /* copy NMO corrected trace to output trace */ memcpy( (void *) tr.data, (const void *) qtn, nt*sizeof(float)); /* else inverse nmo */ } else { /* do inverse nmo via 8-point sinc interpolation */ ints8r(nt,1.0,ft/dt,tr.data,0.0,0.0, nt-itmute,&tnt[itmute],&qt[itmute]); /* apply mute */ for (it=0; it<itmute; ++it) qt[it] = 0.0; /* if specified, undo NMO stretch factor scaling */ if (sscale) for (it=itmute; it<nt; ++it) qt[it] *= at[it]; /* copy inverse NMO corrected trace to output trace */ memcpy( (void *) tr.data, (const void *) qt,nt*sizeof(float)); } /* write output trace */ puttr(&tr); /* remember offset and cdp */ oldoffset = tr.offset; oldcdp = tr.cdp; } while (gettr(&tr)); return(CWP_Exit()); }
int main(int argc, char **argv) { float phase; /* phase shift = phasefac*PI */ float power; /* phase shift = phasefac*PI */ register float *rt; /* real trace */ register complex *ct; /* complex transformed trace */ complex *filt; /* complex power */ int nt; /* number of points on input trace */ size_t ntsize; /* nt in bytes */ int ncdp; /* number of cdps specified */ int icdp; /* index into cdp array */ long oldoffset; /* offset of previous trace */ long oldcdp; /* cdp of previous trace */ int newsloth; /* if non-zero, new sloth function was computed */ int jcdp; /* index into cdp array */ float dt; /* sample spacing (secs) on input trace */ float tn; /* sample spacing (secs) on input trace */ float omega; /* circular frequency */ float domega; /* circular frequency spacing (from dt) */ int nfft; /* number of points in nfft */ int ntnmo; /* number of tnmos specified */ float *cdp; /* array[ncdp] of cdps */ float *vnmo; /* array[nvnmo] of vnmos */ float *ovvt; /* array[nvnmo] of vnmos */ int nvnmo; /* number of tnmos specified */ float *fnmo; /* array[ntnmo] of tnmos */ float **ovv; /* array[nf] of fnmos */ float doffs; /* offset */ float acdp; /* temporary used to sort cdp array */ float *aovv; /* temporary used to sort ovv array */ int invert; /* if non-zero, do invers DLMO */ int cm; /* if non-zero, the offset in cm */ int nf; /* number of frequencies (incl Nyq) */ int it; /* number of frequencies (incl Nyq) */ float onfft; /* 1 / nfft */ float v; /* velocity */ size_t nzeros; /* number of padded zeroes in bytes */ /* Initialize */ initargs(argc, argv); requestdoc(1); /* Set parameters */ power=0.0; /* Get info from first trace*/ if (!gettr(&tr)) err("can't get first trace"); nt = tr.ns; if (!getparfloat("dt", &dt)) dt = ((double) tr.dt)/1000000.0; if (!dt) err("dt field is zero and not getparred"); ntsize = nt * FSIZE; if (!getparint("invert",&invert)) invert = 0; if (!getparint("cm",&cm)) cm = 0; /* Set up for fft */ nfft = npfaro(nt, LOOKFAC * nt); if (nfft >= SU_NFLTS || nfft >= PFA_MAX) err("Padded nt=%d -- too big", nfft); nf = nfft/2 + 1; onfft = 1.0 / nfft; nzeros = (nfft - nt) * FSIZE; domega = TWOPI * onfft / dt; /* get velocity functions, linearly interpolated in frequency */ ncdp = countparval("cdp"); if (ncdp>0) { if (countparname("vnmo")!=ncdp) err("a vnmo array must be specified for each cdp"); if (countparname("fnmo")!=ncdp) err("a tnmo array must be specified for each cdp"); } else { ncdp = 1; if (countparname("vnmo")>1) err("only one (or no) vnmo array must be specified"); if (countparname("fnmo")>1) err("only one (or no) tnmo array must be specified"); } cdp = ealloc1float(ncdp); if (!getparfloat("cdp",cdp)) cdp[0] = tr.cdp; ovv = ealloc2float(nf,ncdp); for (icdp=0; icdp<ncdp; ++icdp) { nvnmo = countnparval(icdp+1,"vnmo"); ntnmo = countnparval(icdp+1,"fnmo"); if (nvnmo!=ntnmo && !(ncdp==1 && nvnmo==1 && ntnmo==0)) err("number of vnmo and tnmo values must be equal"); if (nvnmo==0) nvnmo = 1; if (ntnmo==0) ntnmo = nvnmo; /* equal numbers of parameters vnmo, fnmo */ vnmo = ealloc1float(nvnmo); fnmo = ealloc1float(nvnmo); if (!getnparfloat(icdp+1,"vnmo",vnmo)) vnmo[0] = 400.0; if (!getnparfloat(icdp+1,"fnmo",fnmo)) fnmo[0] = 0.0; for (it=0; it<ntnmo; ++it) fnmo[it]*=TWOPI; for (it=1; it<ntnmo; ++it) if (fnmo[it]<=fnmo[it-1]) err("tnmo values must increase monotonically"); for (it=0,tn=0; it<nf; ++it,tn+=domega) { intlin(ntnmo,fnmo,vnmo,vnmo[0],vnmo[nvnmo-1],1,&tn,&v); ovv[icdp][it] = 1.0/(v); } free1float(vnmo); free1float(fnmo); } /* sort (by insertion) sloth and anis functions by increasing cdp */ for (jcdp=1; jcdp<ncdp; ++jcdp) { acdp = cdp[jcdp]; aovv = ovv[jcdp]; for (icdp=jcdp-1; icdp>=0 && cdp[icdp]>acdp; --icdp) { cdp[icdp+1] = cdp[icdp]; ovv[icdp+1] = ovv[icdp]; } cdp[icdp+1] = acdp; ovv[icdp+1] = aovv; } /* allocate workspace */ ovvt = ealloc1float(nf); /* interpolate sloth and anis function for first trace */ interpovv(nf,ncdp,cdp,ovv,(float)tr.cdp,ovvt); /* set old cdp and old offset for first trace */ oldcdp = tr.cdp; oldoffset = tr.offset-1; /* Allocate fft arrays */ rt = ealloc1float(nfft); ct = ealloc1complex(nf); filt = ealloc1complex(nf); /* Loop over traces */ do { /* if necessary, compute new sloth and anis function */ if (tr.cdp!=oldcdp && ncdp>1) { interpovv(nt,ncdp,cdp,ovv,(float)tr.cdp, ovvt); newsloth = 1; } else { newsloth = 0; } /* if sloth and anis function or offset has changed */ if (newsloth || tr.offset!=oldoffset) { doffs = (fabs)((float)(tr.offset)); if (cm==1) doffs/=100; /* Load trace into rt (zero-padded) */ memcpy( (void *) rt, (const void *) tr.data, ntsize); memset((void *) (rt + nt), (int) '\0', nzeros); /* FFT */ pfarc(1, nfft, rt, ct); /* Apply filter */ { register int i; for (i = 0; i < nf; ++i){ omega = i * domega; if (power < 0 && i == 0) omega = FLT_MAX; if (invert==0) phase = -1.0*omega*ovvt[i]*doffs; else phase = 1.0*omega*ovvt[i]*doffs; /* filt[i] = cmplx(cos(phase),sin(phase)); */ filt[i] = cwp_cexp(crmul(I,phase)); filt[i] = crmul(filt[i], onfft); ct[i] = cmul(ct[i], filt[i]); } } } /* Invert */ pfacr(-1, nfft, ct, rt); /* Load traces back in, recall filter had nfft factor */ { register int i; for (i = 0; i < nt; ++i) tr.data[i] = rt[i]; } puttr(&tr); } while (gettr(&tr)); return EXIT_SUCCESS; }