Waveform filter programs

◆ main()

int main ( int  iargc,
char *  argv[] 
)

Definition at line 187 of file fidasexx.cc.

References cmdlinekeys, Options::debug, Options::doplot, FIDASEXX_VERSION, Options::fileformat, File::filename, Options::fileprefix, formatkey, Trace::free, File::free, Trace::info, File::offset, Options::overwrite, Options::plotdevice, File::rms, Options::rrange, Trace::selected, Trace::series, File::srce, tracekey, Trace::tracenumber, File::traces, Options::verbose, Trace::wid2, and Options::writescaled.

188 {
189 
190  // define usage information
191  char usage_text[]=
192  {
193  FIDASEXX_VERSION "\n"
194  "usage: fidasexx [-v] [-DEBUG] [-type f] [-plot[=dev]]" "\n"
195  " [-overwrite] [-write[=prefix]] [-rmin r] [-rmax r]" "\n"
196  " file [t:l] [f:t] file [t:l] [f:t] [file [t:l] [f:t]...]" "\n"
197  " or: fidasexx --help|-h" "\n"
198  " or: fidasexx --xhelp" "\n"
199  };
200 
201  // define full help text
202  char help_text[]=
203  {
204  "-v be verbose\n"
205  "-DEBUG produce debug output\n"
206  "-type f read and write files of file type \"f\"\n"
207  "-plot[=dev] produce graphical display on PGPLOT device \"dev\"\n"
208  " the specification of \"dev\" is optional\n"
209  "-overwrite overwrite output files in case they already exist\n"
210  "-write[=prefix]\n"
211  " write scaled files; prepend \"prefix\" to file names\n"
212  " to distinguish scaled files and original files\n"
213  "-rmin r use only traces with offset equal or larger than \"r\"\n"
214  "-rmax r use only traces with offset equal or less than \"r\"\n"
215  "\n"
216  "The program expects at least two input files containing seismic data.\n"
217  "Each of the input files is understood to contain data from one single\n"
218  "and unique shot. File specific parameters:\n"
219  "\n"
220  "t:l use only traces from list \"l\" for evaluation\n"
221  " \"l\" may be somtehing like \"2-4,5,7,11\"\n"
222  " all traces are read, tapered and written to the\n"
223  " output; but only traces in range indicated by\n"
224  " \"l\" are used to infer the scaling factor\n"
225  "f:t file has data file type \"t\" instead of the\n"
226  " global format specified by the argument to\n"
227  " \"-type\"\n"
228  "\n"
229  "The program is used to scale data from independent shots to make the\n"
230  "apparent shot amplitude comparable. fidasexx uses a different strategy.\n"
231  "While fidase tries to find optimal scaling factors such that the amplitude\n"
232  "decay with offset is smooth as measured by second differences of rms\n"
233  "values, fidasexx fits the rms values to an explicit amplitude decay with\n"
234  "offset. The underlying model is that rms-values depend on offset r\n"
235  "like\n"
236  " rms(r) = A0 * r**(K),\n"
237  "where r**(K) means \"r to the power of K\".\n"
238  "\n"
239  "If d_(j,k) is the rms value of trace k in file j and r_(j,k) are the\n"
240  "offset of trace k in file j, we search for factors f_j and K such that\n"
241  "the residuals r_(j,k) = log d_(j,k) - (log f_j + K * log r_(j,k))\n"
242  "are minimized in a least squares sense.\n"
243  };
244 
245  // define commandline options
246  using namespace tfxx::cmdline;
247  static Declare options[]=
248  {
249  // 0: print help
250  {"help",arg_no,"-"},
251  // 1: print detailed online help
252  {"xhelp",arg_no,"-"},
253  // 2: verbose mode
254  {"v",arg_no,"-"},
255  // 3: debug mode
256  {"DEBUG",arg_no,"-"},
257  // 4: default file format for input and output
258  {"type",arg_yes,"sff"},
259  // 5: create graphical display
260  {"plot",arg_opt,"/xserve"},
261  // 6: overwrite output
262  {"overwrite",arg_no,"-"},
263  // 7: write scale files
264  {"write",arg_opt,"scaled_"},
265  // 8: write scale files
266  {"rmin",arg_yes,"0."},
267  // 9: write scale files
268  {"rmax",arg_yes,"1.e15"},
269  {NULL}
270  };
271 
272  // no arguments? print usage...
273  if (iargc<2)
274  {
275  cerr << usage_text << endl;
276  cerr << tfxx::seitosh::repository_reference << endl;
277  exit(0);
278  }
279 
280  // collect options from commandline
281  // by creating the instance cmdline of type Commandline (which is a member
282  // of namespace tfxx::cmdline) the command line is parsed; all command line
283  // options defined in the C-array options are extracted and can later be
284  // accessed through the member functions of cmdline
285  Commandline cmdline(iargc, argv, options);
286 
287  // help requested? print full help text...
288  if (cmdline.optset(0))
289  {
290  cerr << usage_text << endl;
291  cerr << help_text << endl;
292  datrw::supported_data_types(cerr);
293  pgplot::basic_device::ldev();
294  cerr << endl << tfxx::seitosh::repository_reference << endl;
295  exit(0);
296  }
297 
298  // help on file format details requested?
299  if (cmdline.optset(1))
300  {
301  cerr << usage_text << endl;
302  cerr << endl;
303  datrw::online_help(cerr);
304  cerr << endl << tfxx::seitosh::repository_reference << endl;
305  exit(0);
306  }
307 
308  // extract commandline options
309  Options opt;
310  opt.verbose=cmdline.optset(2);
311  opt.debug=cmdline.optset(3);
312  opt.fileformat=cmdline.string_arg(4);
313  opt.doplot=cmdline.optset(5);
314  opt.plotdevice=cmdline.string_arg(5);
315  opt.overwrite=cmdline.optset(6);
316  opt.writescaled=cmdline.optset(7);
317  opt.fileprefix=cmdline.string_arg(7);
318  opt.rrange.min=cmdline.float_arg(8);
319  opt.rrange.max=cmdline.float_arg(9);
320 
321  // report program version if in verbose mode
322  if (opt.verbose)
323  { cout << FIDASEXX_VERSION << endl; }
324 
325  // extract commandline arguments
326  // here the rest of the command line is parsed; i.e. the names of input
327  // files together with file specific options
328  TFXX_assert(cmdline.extra(), "missing input file");
329  tfxx::cmdline::Tparsed arguments=parse_cmdline(cmdline, cmdlinekeys);
330 
331  /*----------------------------------------------------------------------*/
332 
333  // here we read the input files
334  // ----------------------------
335 
336  // create a collection of files
337  Tvecoffiles files;
338 
339  // now cycle through the list of input file arguments
340  tfxx::cmdline::Tparsed::const_iterator infilearg=arguments.begin();
341  while (infilearg != arguments.end())
342  {
343  // create a place to store contents of file
344  File infile;
345  // remember name of input file
346  infile.filename=infilearg->name;
347 
348  // open input file
349  // ---------------
350  if (opt.verbose) { cout << "open input file " << infile.filename << endl; }
351  // select file format
352  std::string inputformat=opt.fileformat;
353  // change file format if a specific format was given on the command line
354  // for this file
355  if (infilearg->haskey(formatkey))
356  {
357  inputformat=infilearg->value(formatkey);
358  }
359  // open the input file with appropriate input mode
360  std::ios_base::openmode iopenmode
361  =datrw::ianystream::openmode(inputformat);
362  // open file stream
363  std::ifstream ifs(infile.filename.c_str(), iopenmode);
364  // open seismic time series stream
365  datrw::ianystream is(ifs, inputformat);
366 
367  // read file specific header information
368  is >> infile.srce;
369  is >> infile.free;
370 
371  /*----------------------------------------------------------------------*/
372 
373  // read all traces from this file
374  // ------------------------------
375 
376  // check whether there is a selection of traces defined
377  bool doselect=infilearg->haskey(tracekey);
378 
379  // setup list of trace number ranges
380  typedef tfxx::RangeList<int> Trangelist;
381  Trangelist traceranges=
382  tfxx::string::rangelist<Trangelist::Tvalue>(infilearg->value(tracekey));
383 
384  // count traces
385  int itrace=0;
386 
387  // read next trace, while input stream is good
388  while (is.good())
389  {
390  // count traces
391  ++itrace;
392 
393  // create a place to store trace data
394  Trace trace;
395 
396  // remember number of trace
397  trace.tracenumber=itrace;
398 
399  // read trace data
400  is >> trace.series;
401  is >> trace.wid2;
402  is >> trace.info;
403  is >> trace.free;
404 
405  // we read all traces, but only selected traces are used for fitting
406  trace.selected=(((!doselect) || traceranges.contains(itrace))
407  && opt.rrange.contains(sff::offset(infile.srce,
408  trace.info)));
409 
410  // trace data is read; add to collection
411  infile.traces.push_back(trace);
412 
413  } // while (is.good())
414 
415  /*----------------------------------------------------------------------*/
416 
417  // file data is read; append this file to the collection of files
418  files.push_back(infile);
419 
420  // next input file
421  ++infilearg;
422 
423  } // while (infilearg != arguments.end())
424  // all input time series files are read
425 
426  /*----------------------------------------------------------------------*/
427 
428  if (opt.verbose)
429  {
430  cout << "input files are read..." << endl;
431  cout << "next: count traces" << endl;
432  }
433 
434  /*
435  * All input files are read. Now we have to know the number of traces to be
436  * used in the fitting procedure as well as the number of files for which
437  * scaling factors have to be inferred. In two nested loops we cycle through
438  * all files and traces and count them.
439  */
440 
441  // number of files
442  int nfiles=0;
443  // total number of traces
444  int ntraces=0;
445 
446  Tvecoffiles::const_iterator F=files.begin();
447  while (F!=files.end())
448  {
449  // count file
450  ++nfiles;
451 
452  // count number of selected trace in this file
453  int ninthisfile=0;
454 
455  Tvecoftraces::const_iterator T=F->traces.begin();
456  while (T != F->traces.end())
457  {
458  // count trace if selected
459  if (T->selected) { ++ntraces; ++ninthisfile; }
460  // next trace
461  ++T;
462  } // while (T != F->traces.end())
463 
464  // at least one trace per file has to be used
465  TFXX_assert(ninthisfile>0,
466  "ERROR: at least one trace per file has to be selected");
467 
468  // next file
469  ++F;
470  } // while (F!=files.end())
471 
472  // check whether we have a reasonable number of files
473  TFXX_assert(nfiles>1, "ERROR: we require at least two files!");
474 
475  /*----------------------------------------------------------------------*/
476 
477  if (opt.verbose)
478  {
479  cout << "number of files: " << nfiles << endl;
480  cout << "total number of traces to be used: " << ntraces << endl;
481  cout << "next: set up system of linear equations" << endl;
482  }
483 
484  // at this point a taper should be applied to the traces
485  // this is not yet implemented
486 
487  /*----------------------------------------------------------------------*/
488 
489  /*
490  * Now the dimensions of the least-squares problem are defined. In the next
491  * step we set up the system of linear equations which have to be solved for
492  * the solution of the least-squares problem.
493  *
494  * Data are the logarithms of the rms values of traces. We have as many data
495  * as selected traces.
496  *
497  * Model parameters are the scaling factors for each file (offset to the
498  * logarithmic rms values) and one commen decay exponent (factor to the
499  * logarithmic offset). We have one more model parameter than files.
500  *
501  * If d_(j,k) is the rms value of trace k in file j and r_(j,k) are the
502  * offset of trace k in file j, we search for factors f_j and K such that
503  * the residuals r_(j,k) = log d_(j,k) - (log f_j + K * log r_(j,k))
504  * are minimized in a least squares sense.
505  */
506 
507  // values to be prepared
508  // ---------------------
509 
510  // vector of model parameters
511  linear::TDmatrix m(nfiles+1);
512  m=0.;
513 
514  // vector of data values (logarithm of rms of time series)
515  linear::TDmatrix d(ntraces);
516  d=0.;
517 
518  // vector of offset values
519  linear::TDmatrix r(ntraces);
520  r=0.;
521 
522  // remember file index for given trace
523  typedef std::vector<int> Tvecofint;
524  Tvecofint fileindex(ntraces);
525 
526  // matrix of partial derivatives
527  linear::TDmatrix D(ntraces, nfiles+1);
528  D=0.;
529 
530  // count traces separately
531  // initialize with first index value for vector d
532  int itrace=d.first(0);
533 
534  // fill d, r, fileindex, and D with appropriate values
535  // ---------------------------------------------------
536  for (unsigned int i=0; i<files.size(); ++i)
537  {
538  // reference to current file (just for convenience)
539  const File& currentfile=files[i];
540  // cycle through all traces in this file
541  for (unsigned int j=0; j<currentfile.traces.size(); ++j)
542  {
543  // reference to current trace (just for convenience)
544  const Trace& currenttrace=currentfile.traces[j];
545  // operate on trace, if trace is selected
546  if (currenttrace.selected)
547  {
548  // just check the index to make program bullet proof
549  TFXX_assert(itrace<=d.last(0),
550  "ERROR: illegal vector index - inconsistency in program");
551 
552  d(itrace)=std::log(aff::func::rms(currenttrace.series));
553  r(itrace)=sff::offset(currentfile.srce,currenttrace.info);
554  // check that coordinates are reasonable
555  TFXX_assert(r(itrace)>1.e-6,
556  "ERROR: offset is unreasonably small (possibly zero)");
557  D(itrace,i+D.first(1))=1.;
558  D(itrace,D.last(1))=std::log(r(itrace));
559  fileindex[itrace-d.first(0)]=i;
560 
561  // we filled this value; proceeed to next one
562  ++itrace;
563  } // if (currenttrace.selected)
564  } // for (unsigned int j=0; j<currentfile.traces.size(); ++j)
565  } // for (int i=0; i<files.size(); ++i)
566 
567  if (opt.verbose)
568  {
569  cout << "system of linear equations is ready" << endl;
570  }
571 
572  // setup system of linear equations
573  // --------------------------------
574  linear::TDmatrix M=linear::op::dotNxM(linear::op::transposeNxM(D),D);
575  linear::TDmatrix R=linear::op::dotNxM(linear::op::transposeNxM(D),d);
576 
577  // solve system of linear equations
578  // --------------------------------
579  m=linear::lapack::dposv(M,R);
580 
581  // calculate scaling factors
582  Tseries factor(0,nfiles-1);
583  Tvalue firstamp=std::exp(m(m.first(0)));
584  for (int i=0; i<=factor.last(); ++i)
585  {
586  factor(i)=firstamp/std::exp(m(m.first(0)+i));
587  }
588  Tvalue attenuation=m(m.last(0));
589 
590  if (opt.verbose)
591  {
592  cout << "system of linear equations is solved" << endl;
593  cout << "power-law attentuation exponent is " << attenuation << endl;
594  }
595 
596  /*----------------------------------------------------------------------*/
597 
598  // extract ranges for plot
599  pgplot::Trange offsetrange(0.,0.), rmsrange(0.,0.);
600 
601  // scale files
602  // -----------
603  for (unsigned int i=0; i<files.size(); ++i)
604  {
605  File& currentfile=files[i];
606  currentfile.rms=pgplot::pgaff::Tseries(0,currentfile.traces.size()-1);
607  currentfile.offset=pgplot::pgaff::Tseries(0,currentfile.traces.size()-1);
608  if (opt.verbose)
609  {
610  cout << "scale file #" <<i+1 << " "
611  << currentfile.filename << " by " << factor(i) << endl;
612  }
613  for (unsigned int j=0; j<currentfile.traces.size(); ++j)
614  {
615  currentfile.traces[j].series *= factor(i);
616  currentfile.offset(j)=std::log10(sff::offset(currentfile.srce,
617  currentfile.traces[j].info));
618  currentfile.rms(j)=std::log10(aff::func::rms(currentfile.traces[j].series));
619  } // for (int j=0; j<=traces.size(); ++j)
620 
621  // check ranges for subsequent plot
622  if (i==0)
623  {
624  offsetrange=pgplot::pgaff::series_value_range(currentfile.offset);
625  rmsrange=pgplot::pgaff::series_value_range(currentfile.rms);
626  }
627  else
628  {
629  offsetrange.extend(pgplot::pgaff::series_value_range(currentfile.offset));
630  rmsrange.extend(pgplot::pgaff::series_value_range(currentfile.rms));
631  }
632  } // for (int i=0; i<=files.size(); ++i)
633 
634  /*----------------------------------------------------------------------*/
635 
636  // plot
637  // ----
638 
639  if (opt.doplot)
640  {
641  pgplot::device dev(opt.plotdevice.c_str());
642  dev.env(pgplot::Trect(offsetrange,rmsrange), 0, 30);
643  dev.lab("offset / m","rms value","rms amplitude of scaled traces");
644  for (unsigned int i=0; i<files.size(); ++i)
645  {
646  File& currentfile=files[i];
647  pgplot::pgaff::pt(dev, currentfile.offset, currentfile.rms, 2+i);
648  } // for (int i=0; i<=files.size(); ++i)
649  const int npts=500;
650  pgplot::pgaff::Tseries x(0,npts-1);
651  pgplot::pgaff::Tseries y(0,npts-1);
652  for (int i=0; i<npts; ++i)
653  {
654  x(i)=offsetrange.min+i*offsetrange.fullrange()/(npts-1);
655  y(i)=std::log10(firstamp)+attenuation*x(i);
656  }
657  pgplot::pgaff::line(dev, x, y);
658  } // if (opt.doplot)
659 
660  /*----------------------------------------------------------------------*/
661 
662  // write scaled files
663  // ------------------
664 
665  if (opt.writescaled)
666  {
667  if (opt.verbose) { cout << "write scaled files" << endl; }
668 
669  for (unsigned int i=0; i<files.size(); ++i)
670  {
671  File& currentfile=files[i];
672  std::string ofilename=opt.fileprefix+currentfile.filename;
673  if (opt.verbose)
674  {
675  cout << "write file " << ofilename << endl;
676  }
677 
678  // create string to comment scaling
679  std::ostringstream oss;
680  oss << "scaled by factor " << factor(i)
681  << "; decay constant is " << attenuation;
682 
683  // add information to file free block
684  currentfile.free.append(std::string(FIDASEXX_VERSION));
685  currentfile.free.append(oss.str());
686 
687  // create output stream of desired file format
688  std::ios_base::openmode oopenmode
689  =datrw::oanystream::openmode(opt.fileformat);
690  std::ofstream ofs(ofilename.c_str(), oopenmode);
691  datrw::oanystream os(ofs, opt.fileformat, opt.debug);
692 
693  // write srce data and file free block if supported
694  if (os.handlessrce()) { os << currentfile.srce; }
695  if (os.handlesfilefree()) { os << currentfile.free; }
696 
697  // write trace data
698  for (unsigned int j=0; j<currentfile.traces.size(); ++j)
699  {
700  if (opt.verbose)
701  {
702  cout << " write trace #" << j+1 << endl;
703  }
704  Trace& currenttrace=currentfile.traces[j];
705 
706  // add information to file free block
707  currenttrace.free.append(oss.str());
708 
709  os << currenttrace.wid2;
710  if (os.handlesinfo()) { os << currenttrace.info; }
711  if (os.handlesfilefree()) { os << currenttrace.free; }
712  os << currenttrace.series;
713  } // for (unsigned int j=0; j<currentfile.traces.size(); ++j)
714  } // for (int i=0; i<=files.size(); ++i)
715  } // if (opt.writescaled)
716 
717 } // main()
aff::Series< Tvalue > Tseries
Definition: fidasexx.cc:139
static const char tracekey[]
Definition: fidasexx.cc:125
pgplot::Trange rrange
Definition: fidasexx.cc:116
std::string fileformat
Definition: fidasexx.cc:104
Tvecoftraces traces
Definition: fidasexx.cc:174
bool writescaled
Definition: fidasexx.cc:112
Tseries series
Definition: fidasexx.cc:146
static const char * cmdlinekeys[]
Definition: fidasexx.cc:131
sff::WID2 wid2
Definition: fidasexx.cc:152
bool selected
Definition: fidasexx.cc:150
double Tvalue
Definition: fidasexx.cc:136
static const char formatkey[]
Definition: fidasexx.cc:128
std::vector< File > Tvecoffiles
Definition: fidasexx.cc:183
bool doplot
Definition: fidasexx.cc:108
bool overwrite
Definition: autocorr.cc:61
int tracenumber
Definition: fidasexx.cc:148
bool debug
Definition: autocorr.cc:61
sff::FREE free
Definition: fidasexx.cc:172
#define FIDASEXX_VERSION
Definition: fidasexx.cc:36
pgplot::pgaff::Tseries rms
Definition: fidasexx.cc:176
sff::FREE free
Definition: fidasexx.cc:156
bool verbose
Definition: autocorr.cc:61
sff::INFO info
Definition: fidasexx.cc:154
std::string filename
Definition: fidasexx.cc:168
aff::Series< double > Tseries
Definition: cross.cc:69
std::string plotdevice
Definition: fidasexx.cc:106
pgplot::pgaff::Tseries offset
Definition: fidasexx.cc:178
std::string fileprefix
Definition: fidasexx.cc:114
sff::SRCE srce
Definition: fidasexx.cc:170