conv/many suite: convert (m)any seismic data format(s)
anyextract.cc
Go to the documentation of this file.
1 
88 #define ANYEXTRACT_VERSION \
89  "ANYEXTRACT V1.27 extract data files, using index file"
90 
91 #include <fstream>
92 #include <iostream>
93 #include <list>
94 #include <vector>
95 #include <string>
96 #include <sstream>
97 #include <aff/seriesoperators.h>
98 #include <tfxx/misc.h>
99 #include <tfxx/commandline.h>
100 #include <tfxx/stringfunc.h>
101 #include <tfxx/error.h>
102 #include <tfxx/seitosh.h>
103 #include <datrwxx/tracereader.h>
104 #include <libtime++.h>
105 #include <tfxx/regexx.h>
106 #include <datrwxx/formats.h>
107 #include <datrwxx/error.h>
108 #include <datrwxx/writeany.h>
109 #include "sub/structgapanalysis.h"
110 #include "sub/gapfunctions.h"
111 #include "sub/completenessbins.h"
112 #include "sub/structgapseries.h"
113 
114 /*----------------------------------------------------------------------*/
115 
116 struct Options {
119  libtime::TAbsoluteTime first;
120  libtime::TAbsoluteTime last;
122  std::string selstation;
123  std::string selchannel;
124  std::string selinstrument;
125  std::string selauxid;
126  std::string outputformat;
131  bool setcalib;
132  bool setcalper;
135  std::string gapseriesfile;
138  bool printgaps;
139  std::string gapoutputfile;
140  std::string binsize;
141  unsigned int summarizelevel;
143  std::string gnuplotfile;
144 }; // struct Options
145 
146 /*----------------------------------------------------------------------*/
147 
148 using std::cout;
149 using std::cerr;
150 using std::endl;
151 
152 /*----------------------------------------------------------------------*/
153 
154 typedef std::vector<std::string> Tvecofstrings;
155 
156 /*----------------------------------------------------------------------*/
157 
158 typedef datrw::Tdseries Tseries;
161 
162 /*----------------------------------------------------------------------*/
163 
165 class Series {
166  public:
167  typedef Tseries Tds;
168  typedef Tiseries Tis;
169  typedef Tfseries Tfs;
170  typedef aff::Tsubscript Tindex;
171  typedef aff::Tsize Tsize;
172  typedef Tis::Tshape Tshape;
173  Series():
174  Mselecti(false), Mselectd(false), Mselectf(false) { }
175  bool selected() const { return(Mselecti || Mselectd || Mselectf); }
176  Tds& ds()
177  {
178  TFXX_assert(!(Mselecti || Mselectf),
179  "ERROR (Series): other type is already slected!\n"
180  "internal inconsistency to be considered a bug");
181  Mselectd=true;
182  return(Mds);
183  }
184  Tfs& fs()
185  {
186  TFXX_assert(!(Mselecti || Mselectd),
187  "ERROR (Series): other type is already slected!\n"
188  "internal inconsistency to be considered a bug");
189  Mselectf=true;
190  return(Mfs);
191  }
192  Tis& is()
193  {
194  TFXX_assert(!(Mselectd || Mselectf),
195  "ERROR (Series): other type is already slected!\n"
196  "internal inconsistency to be considered a bug");
197  Mselecti=true;
198  return(Mis);
199  }
200  Tshape shape() const
201  {
202  Tshape retval;
203  TFXX_assert(this->selected(), "ERROR (Series): no type is selected!\n"
204  "internal inconsistency to be considered a bug");
205  if (Mselectd)
206  { retval=Mds.shape(); }
207  else if (Mselecti)
208  { retval=Mis.shape(); }
209  else
210  { retval=Mfs.shape(); }
211  return(retval);
212  }
213  Tindex first() const
214  { return this->shape().first(); }
215  Tindex last() const
216  { return this->shape().last(); }
217  private:
218  // integer is selected
219  bool Mselecti;
220  // double is selected
221  bool Mselectd;
222  // float is selected
223  bool Mselectf;
224  // double type
225  Tds Mds;
226  // integer type
228  // float type
230 }; // class Series
231 
232 /*======================================================================*/
233 // data structures and type used to handle collections of index entries
234 // use to collect and sort index entries required to assemble the requested
235 // data set
236 
241 struct IndexEntry {
242  // name of data file (with path)
243  std::string filename;
244  // index of trace in data file
245  int itrace;
246  // format of data file
247  std::string dataformat;
248  // WID2 line for trace
249  sff::WID2 wid2;
250 }; // struct IndexEntry
251 
253 typedef std::vector<IndexEntry> Tvecofindexentries;
254 
255 /*----------------------------------------------------------------------*/
256 
262  tfxx::string::regexx station;
263  tfxx::string::regexx channel;
264  tfxx::string::regexx instrument;
265  tfxx::string::regexx auxid;
266 }; // struct SelectionRegexx
267 
268 /*----------------------------------------------------------------------*/
269 
277 typedef std::list<int> Tintlist;
278 
283 typedef std::vector<Tintlist> Tvecofintlist;
284 
285 /*----------------------------------------------------------------------*/
286 
292  public:
294  Mcollection(collection) { }
295  bool operator()(const int& i1, const int& i2)
296  { return(Mcollection[i1].wid2.date<Mcollection[i2].wid2.date); }
297  private:
299 }; // class CompareCollection
300 
301 /*----------------------------------------------------------------------*/
302 
304 std::ostream& operator<<(std::ostream& os, const IndexEntry& entry)
305 {
306  std::string timestring=entry.wid2.date.timestring();
307  os << timestring.substr(4,23) << " ";
308  os << entry.wid2.station << " ";
309  os << entry.wid2.channel << " ";
310  os << entry.wid2.auxid << " ";
311  os << entry.wid2.instype << " ";
312  os << entry.filename << " ";
313  os << entry.itrace << " ";
314  os << entry.dataformat << " ";
315  return(os);
316 } // report an Index Entry
317 
318 /*======================================================================*/
319 // data structure used to assemble actual data sets (not yet samples but
320 // all information necessary to actually read and collect samples)
321 
329 struct DataBlock {
330  // link to index entry
331  int ientry;
332  // first sample in input data trace
333  int ifirst;
334  // first sample in output data trace
335  int ofirst;
336  // number of samples to copy from input to output
337  int nsamples;
338 }; // struct DataBlock
339 
344 typedef std::vector<DataBlock> Tvecofblocks;
345 
352 typedef std::vector<Tvecofblocks> Tvecoftraces;
353 
354 /*======================================================================*/
355 // main program
356 // ============
357 
358 int main(int iargc, char* argv[])
359 {
360 
361  // define usage information
362  char usage_text[]=
363  {
364  ANYEXTRACT_VERSION "\n"
365  "usage: anyextract [common options] [extract options]\n"
366  " index [ index [...] ] outfile\n"
367  " or: anyextract -GAPFIND [common options] [gap options]\n"
368  " index [ index [...] ]\n"
369  " or: anyextract --help|-h|-xhelp" "\n"
370  "\n"
371  "common options are:\n"
372  " [-verbose] [-DEBUG] [-dump]\n"
373  " [-type f] [-overwrite]\n"
374  " [-sfirst date] [-slast date] [-sduration dur]\n"
375  " [-sstation regex] [-schannel regex]\n"
376  " [-sinstrument regex] [-sauxid regex]\n"
377  " [-dtr f] [-tr] [-br]\n"
378  "extract options are:\n"
379  " [-GSE] [-int] [-float] [-nofree]" "\n"
380  " [-calib f] [-calper p]" "\n"
381  " [-RANGECHECK]\n"
382  "gap options are:\n"
383  " [-GAPFIND] [-Ggs f] [-Gcs f] [-Gprint[=file]]" "\n"
384  " [-Gbin s] [-Gsummarize l] [-Ggpt f]" "\n"
385  };
386 
387  // define help text
388  char help_text[]=
389  {
390  "read index file(s) and extract defined parts of the dataset" "\n"
391  "\n"
392  "You have to use \"anyindex\" first to create one or more index" "\n"
393  "files referencing the data files. \"anyextract\" will scan these" "\n"
394  "index files and decide from which data files the requested" "\n"
395  "dataset can be compiled. It will arrange this information" "\n"
396  "and build chains of input datasets for each unique stream" "\n"
397  "(defined by station, channel, instrument and auxid) and will" "\n"
398  "then read and compile the time series for the output file." "\n"
399  "\n"
400  "The input file type including file type modifiers is defined in the\n"
401  "index file. The output file type as well as the data type (float,\n"
402  "double, or int) used for copying samples can be selcted on the\n"
403  "command line.\n"
404  "\n"
405  "The program can be executed in two differen modes:\n"
406  "1. data extraction: reads the index and assembles data\n"
407  "2. gap analysis: reads the index and evaluates gaps in the data\n"
408  "\n"
409  "Command line arguments and options:\n"
410  " (command line options may be abbreviated, i.e. \"-v\", \"-verb\",\n"
411  " and \"-verbose\" are all equivalent)\n"
412  "\n"
413  "-help print online help\n"
414  "-xhelp provides extended online help (explains data formats etc.)\n"
415  "\n"
416  "index ... index file(s)" "\n"
417  "\n"
418  "Options common to both modes:\n"
419  " -verbose be verbose" "\n"
420  " -DEBUG debugging output (be very verbose)" "\n"
421  " -dump dump intermediate results" "\n"
422  "\n"
423  " -overwrite overwrite existing output files" "\n"
424  "\n"
425  " Data selection:\n"
426  " -sfirst date date and time of first sample to extract\n"
427  " -slast date date and time of last sample to extract\n"
428  " -sduration dur define end of time window by duration \"dur\"\n"
429  " -sstation regex select station by regular expression \"regex\"\n"
430  " -schannel regex select channel by regular expression \"regex\"\n"
431  " -sinstrument regex select instrument by regular expression \"regex\"\n"
432  " -sauxid regex select auxid by regular expression \"regex\"\n"
433  "\n"
434  " Options to control the handling of inconsitencies:\n"
435  " -dtr f allow tolerance when matching times of consecutive\n"
436  " data blocks; ''f'' defines the tolerance as a fraction\n"
437  " of the sampling interval, that is tolerated for the\n"
438  " residual of sample times\n"
439  " Notice: the tolerance is tested against the residual\n"
440  " of consecutive input blocks, not against the residual\n"
441  " of all extracted samples and the next input block\n"
442  " -br redundant input samples are a break condition;\n"
443  " program does not abort\n"
444  " -tr tolerate redundant samples; i.e. do not abort if input\n"
445  " blocks are overlapping, which means that the same\n"
446  " exists twice in different input blocks\n"
447  " this clears the -br option if set\n"
448  "\n"
449  " Option to select file type for time series output:\n"
450  " -type f write output file of format \"f\"\n"
451  " in GAPFIND mode this is used together with options\n"
452  " \"-Ggs\" and \"-Gcs\"\n"
453  "\n"
454  "Options controlling data extraction:\n"
455  " outfile output file (do not specify this in gap finding" "\n"
456  " mode, i.e. together with option -GAPFIND)" "\n"
457  "\n"
458  " Options to select file type for time series output:\n"
459  " -type f write output file of format \"f\"\n"
460  " -GSE write GSE compatible data" "\n"
461  " setting this option implies option -int" "\n"
462  " and option \"-type gse\"" "\n"
463  " -int use integer data type for copying of samples" "\n"
464  " -float use float (single precision) data type for copying of\n"
465  " samples" "\n"
466  "\n"
467  " Options to adjust content of headers in output files:\n"
468  " -calib f set calib entry in output file to f" "\n"
469  " see notes below" "\n"
470  " -calper p set calper entry in output file to p" "\n"
471  " -nofree do not write FREE blocks, even if output format supports\n"
472  " FREE blocks (just speeds up data I/O of subsequent\n"
473  " operations)\n"
474  "\n"
475  " Option for debugging purposes:\n"
476  " -RANGECHECK perform array index range check (debug option)" "\n"
477  "\n"
478  "Options controlling gap analysis:\n"
479  " -GAPFIND find only gaps - do not extract data\n"
480  " do not specify an output file in this case\n"
481  " the -verbose option increases the verbosity of gap\n"
482  " reports\n"
483  " -Gbin s set bin size for gap and completeness series\n"
484  " -Ggs f gap distribution will be written to file \"f\"\n"
485  " the output file is a time series file in format\n"
486  " specified by option \"-type f\"\n"
487  " it specifies the number of missing samples in each bin\n"
488  " as specified by option \"-Gbin s\"\n"
489  " -Gcs f completeness distribution will be written to file \"f\"\n"
490  " the output file is a time series file in format\n"
491  " specified by option \"-type f\"\n"
492  " it specifies the completeness of the data in each bin\n"
493  " as specified by option \"-Gbin s\"in per cent, where\n"
494  " 100% means that no sample is missing\n"
495  " -Gprint[=f] print a list of gaps to stdout\n"
496  " if \"f\" is defined, write this list to file \"f\"\n"
497  " -Gsummarize l set summerize level for -Gprint to \"l\"\n"
498  " l=1: summarize results for each stream\n"
499  " l=2: summarize total results only\n"
500  " l=3: just output total number of gaps\n"
501  " l=4: just output total number of missing samples\n"
502  " -Ggpt f create gnuplot plot file with basename \"f\"\n"
503  " the filename will be complemented by the extension\n"
504  " \".gpt\"; by running gnuplot on this file, a graphical\n"
505  " display of missing data organized in bins of the size\n"
506  " specified by option \"-Gbin s\" is created in a\n"
507  " Postscript file with basename \"f\" and extension \".ps\"\n"
508  " Notice: Sample index values typically are represented by variables\n"
509  " of type int (integers of 4 bytes). The maximum number of\n"
510  " samples which can by handled that way is slightly more than\n"
511  " 2.e9, which is fully sufficient when handling actual time\n"
512  " series.\n"
513  " When doing gap-analysis you may run into cases where\n"
514  " this range is exceeded. If sampling rate is larger than 68 sps\n"
515  " the total number of samples for one year exceeds the value\n"
516  " range. Take in mind, that such cases might not be handled\n"
517  " correctly.\n"
518  " This limitation is imposed on the program by the used software\n"
519  " libraries and cannot easily be overcome.\n"
520  };
521 
522  // define extended help text
523  char extended_help_text[]=
524  {
525  "calib and calper" "\n"
526  "----------------" "\n"
527  " The definition of the parameters calib and calper in the GSE2.0" "\n"
528  " format specification is ambigious. The format caontains no field" "\n"
529  " that is able to specify whether the sensor has the response of" "\n"
530  " an electrodynamic seismometer or an accelerometer, but the" "\n"
531  " conversion factor calib is given in units of displacement." "\n"
532  " It is not specified, whether the factor has to be applied" "\n"
533  " with deconvolution (which would be reasonable, since units" "\n"
534  " are given relative to displacement) or without deconvolution" "\n"
535  " as is common practice. For this reason there exists only a kind" "\n"
536  " of convention how this fields are used. Since these fields at least" "\n"
537  " require the knowledge of the instrument's response, the program" "\n"
538  " usually sets both parameters to the default value -1. in the" "\n"
539  " output data. But beware: Some programs like SeismicHandler" "\n"
540  " rely on these fields, when reading GSE data. They will reject" "\n"
541  " the default -1. and replace the value by 1., which results in" "\n"
542  " a scaling of amplitudes with a factor 2*pi which is usually" "\n"
543  " not desired. In these cases it is save to choose" "\n"
544  " -calib 1. -calper 6.2831853" "\n"
545  " or" "\n"
546  " -calib 0.15915494 -calper 1." "\n"
547  " With these settings, the input data will not be scaled when" "\n"
548  " read into SeismicHandler." "\n"
549  };
550 
551  // define commandline options
552  using namespace tfxx::cmdline;
553  static Declare options[]=
554  {
555  // 0: print help
556  {"help",arg_no,"-"},
557  // 1: verbose mode
558  {"verbose",arg_no,"-"},
559  // 2: overwrite mode
560  {"overwrite",arg_no,"-"},
561  // 3: first date
562  {"sfirst",arg_yes,"-"},
563  // 4: last date
564  {"slast",arg_yes,"-"},
565  // 5: select station
566  {"sstation",arg_yes,".*"},
567  // 6: select channel
568  {"schannel",arg_yes,".*"},
569  // 7: select instrument
570  {"sinstrument",arg_yes,".*"},
571  // 8: select auxid
572  {"sauxid",arg_yes,".*"},
573  // 9: debug mode
574  {"DEBUG",arg_no,"-"},
575  // 10: range check debug mode
576  {"RANGECHECK",arg_no,"-"},
577  // 11: find gaps only
578  {"GAPFIND",arg_no,"-"},
579  // 12: tolerate input time residuals
580  {"dtr",arg_yes,"0."},
581  // 13: tolerate redundant input samples
582  {"tr",arg_no,"-"},
583  // 14: break chain on redundant input samples
584  {"br",arg_no,"-"},
585  // 15: dump intermediate results
586  {"dump",arg_no,"-"},
587  // 16: define window by duration
588  {"sduration",arg_yes,"-"},
589  // 17: extract integer data
590  {"int",arg_no,"-"},
591  // 18: write GSE compatible SFF
592  {"GSE",arg_no,"-"},
593  // 19: set calib
594  {"calib",arg_yes,"-1."},
595  // 20: set calper
596  {"calper",arg_yes,"-1."},
597  // 21: detailed help text
598  {"xhelp",arg_no,"-"},
599  // 22: do not write FREE blocks
600  {"nofree",arg_no,"-"},
601  // 23: select output file format
602  {"type",arg_yes,"sff"},
603  // 24: use float type series for copying
604  {"float",arg_no,"-"},
605  // 25: set bin size for completeness analysis
606  {"Gbin",arg_yes,"0/1"},
607  // 26: print a list of gaps
608  {"Gprint",arg_opt,"-"},
609  // 27: write gap time series to file
610  {"Ggs",arg_yes,"-"},
611  // 28: write completeness time series to file
612  {"Gcs",arg_yes,"-"},
613  // 29: set summarize level
614  {"Gsummarize",arg_yes,"0"},
615  // 30: gnuplot file
616  {"Ggpt",arg_yes,"-"},
617  {NULL}
618  };
619 
620  // no arguments? print usage...
621  if (iargc<2)
622  {
623  cerr << usage_text << endl;
624  cerr << tfxx::seitosh::repository_reference << endl;
625  exit(0);
626  }
627 
628  // collect options from commandline
629  Commandline cmdline(iargc, argv, options);
630 
631  // help requested? print full help text...
632  if (cmdline.optset(0) || cmdline.optset(21))
633  {
634  cerr << usage_text << endl;
635  cerr << help_text << endl;
636  datrw::supported_data_types(cerr);
637  if (cmdline.optset(21))
638  {
639  cerr << endl << extended_help_text << endl;
640  datrw::online_help(cerr);
641  cerr << endl;
642  cerr << libtime::usage_time_format_string << endl;
643  }
644  cerr << endl << tfxx::seitosh::repository_reference << endl;
645  exit(0);
646  }
647 
648  Options opt;
649 
650  opt.verbose=cmdline.optset(1);
651  opt.overwrite=cmdline.optset(2);
652  opt.firstset=cmdline.optset(3);
653  opt.lastset=cmdline.optset(4);
654  if (opt.firstset) { opt.first=libtime::TAbsoluteTime(cmdline.string_arg(3)); }
655  if (opt.lastset) { opt.last=libtime::TAbsoluteTime(cmdline.string_arg(4)); }
656  opt.selstation=cmdline.string_arg(5);
657  opt.selchannel=cmdline.string_arg(6);
658  opt.selinstrument=cmdline.string_arg(7);
659  opt.selauxid=cmdline.string_arg(8);
660  opt.debug=cmdline.optset(9);
661  if (opt.debug) { opt.verbose=true; }
662  opt.rangecheck=cmdline.optset(10);
663  opt.findgapsonly=cmdline.optset(11);
664  opt.allowtolerance=cmdline.optset(12);
665  opt.relativetolerance=cmdline.double_arg(12);
666  opt.allowduplicatesamples=cmdline.optset(13);
667  opt.breakonduplicatesamples=cmdline.optset(14);
668  opt.dumpintermediateresults=cmdline.optset(15);
669  // handle setting time window by duration
670  if (cmdline.optset(16))
671  {
672  TFXX_assert(opt.firstset,
673  "ERROR: you must specify the beginning of the time window too");
674  TFXX_assert(!opt.lastset,
675  "ERROR: conflicting definitions for time window");
676  opt.lastset=true;
677  opt.last=opt.first+libtime::TRelativeTime(cmdline.string_arg(16));
678  }
679  opt.integerdata=(cmdline.optset(17)||cmdline.optset(18));
680  opt.GSEoutput=cmdline.optset(18);
681  opt.setcalib=cmdline.optset(19);
682  opt.newcalib=cmdline.double_arg(19);
683  opt.setcalper=cmdline.optset(20);
684  opt.newcalper=cmdline.double_arg(20);
685  opt.nofreeblock=cmdline.optset(22);
686  opt.outputformat=cmdline.string_arg(23);
687  opt.floatdata=cmdline.optset(24);
688  opt.binsize=cmdline.string_arg(25);
689  opt.printgaps=cmdline.optset(26);
690  opt.gapoutputfile=cmdline.string_arg(26);
691  opt.writegapseries=cmdline.optset(27);
692  opt.gapseriesfile=cmdline.string_arg(27);
693  opt.writecompleteness=cmdline.optset(28);
694  opt.completenessseriesfile=cmdline.string_arg(28);
695  opt.summarizelevel=static_cast<unsigned int>(cmdline.int_arg(29));
696  opt.providegnuplotplot=cmdline.optset(30);
697  opt.gnuplotfile=cmdline.string_arg(30);
698 
699  // is any of the GAP analysis modes activated
700  bool doGAPanalysis=opt.findgapsonly
701  || opt.printgaps || opt.writegapseries || opt.writecompleteness
702  || opt.providegnuplotplot;
703 
704  // hierarchical definition of duplicate sample conditions
706 
707  if (opt.verbose)
708  {
709  cout << ANYEXTRACT_VERSION << endl;
710  }
711 
712  // check special file format settings
713  if (opt.GSEoutput)
714  {
715  cout << "GSE output selected: ";
716  opt.outputformat="gse";
717  opt.integerdata=true;
718  cout << "set output format to \"" << opt.outputformat << "\" ";
719  cout << "set internal data type to integer" << endl;
720  }
721 
722  // setup vector of input filenames and read command line
723  Tvecofstrings infiles;
724  std::string outfile;
725  TFXX_assert(cmdline.extra(), "ERROR: missing index file!");
726  outfile=cmdline.next();
727  // collect input files
728  while (cmdline.extra())
729  {
730  // cout << outfile << " ";
731  infiles.push_back(outfile);
732  outfile=cmdline.next();
733  // cout << outfile << " # ";
734  }
735  if (doGAPanalysis)
736  {
737  infiles.push_back(outfile);
738 
739  if (opt.verbose || (opt.summarizelevel < 3))
740  {
741  cout << "SPECIAL MODE: find gaps in input data - do not extract data"
742  << endl;
743  }
744  }
745  else
746  {
747  TFXX_assert((infiles.size()>0), "ERROR: missing output file!");
748  }
749 
750  /*----------------------------------------------------------------------*/
751  // stage 0 dump:
752  if (opt.dumpintermediateresults)
753  {
754  cout << endl;
755  cout << "DUMP stage 0 results: names of index files to process" << endl;
756  Tvecofstrings::const_iterator iv=infiles.begin();
757  while (iv!=infiles.end())
758  {
759  cout << " " << *iv << endl;
760  ++iv;
761  }
762  cout << " output will be written to:" << endl
763  << " " << outfile << endl;
764  cout << endl;
765  }
766 
767 
768  /*
769  * strategy:
770  *
771  * 1. read all index file entries and check whether they match the selection
772  * fill them into a vector if they do
773  * 2. collect matching data streams in order of increasing time
774  * 3. find gaps and setup traces for output file
775  * 4. read data and write it to the output file
776  */
777 
778  /*======================================================================*/
779  /* 1. scan index files and collect matching entries
780  *
781  * In this section all index files will be read. Each entry will be checked
782  * whether ist matches the station, channel, instrument, and auxid selection
783  * and whether its time window lies within the selected window or at least
784  * overlaps with the selection. All matching entries will be collected
785  * in a global variable
786  *
787  * Tvecofindexentries collection;
788  *
789  */
790  if (opt.verbose || opt.findgapsonly)
791  {
792  cout << endl;
793  cout << "step 1: collect matching index entries" << endl;
794  cout << "data selection:" << endl;
795  if (opt.firstset)
796  { cout << " first sample: " << opt.first.timestring() << endl; }
797  else
798  { cout << " first sample: no time specified" << endl; }
799  if (opt.lastset)
800  { cout << " last sample: " << opt.last.timestring() << endl; }
801  else
802  { cout << " last sample: no time specified" << endl; }
803  if (opt.allowduplicatesamples)
804  cout << " duplicate input samples are tolerated" << endl;
805  if (opt.breakonduplicatesamples)
806  cout << " duplicate input samples are a break condition" << endl;
807  if (opt.allowtolerance)
808  cout << " sampling raster tolerance is "
809  << opt.relativetolerance
810  << " of sampling interval" << endl;
811  }
812 
813  // plausibility test
814  if (opt.lastset && opt.firstset)
815  {
816  TFXX_assert(opt.first<opt.last,
817  "ERROR: selected time window makes no sense!");
818  }
819 
820  // prepare regular expressions
821  SelectionRegexx rgxx;
822  rgxx.station.expression(opt.selstation);
823  rgxx.channel.expression(opt.selchannel);
824  rgxx.instrument.expression(opt.selinstrument);
825  rgxx.auxid.expression(opt.selauxid);
826 
827  if (opt.verbose || opt.findgapsonly)
828  {
829  cout << " station: " << rgxx.station.expression() << endl;
830  cout << " channel: " << rgxx.channel.expression() << endl;
831  cout << " instrument: " << rgxx.instrument.expression() << endl;
832  cout << " auxid: " << rgxx.auxid.expression() << endl;
833  }
834 
835  // vector of matching entries (my collection)
836  Tvecofindexentries collection;
837 
838  // scan
839  Tvecofstrings::const_iterator infile=infiles.begin();
840  while( infile!=infiles.end())
841  {
842  if (opt.verbose || opt.findgapsonly)
843  { cout << "** open next index file: " << *infile << endl; }
844  std::ifstream is(infile->c_str());
845 
846  // number of entries scanned
847  int nscanned=0;
848  // start reading here to trigger is flags
849  IndexEntry indexentry;
850  is >> indexentry.filename;
851  while(is.good())
852  {
853  if (opt.debug)
854  { cout << "DEBUG: read next entry:" << endl; }
855  // first, just read
856  is >> indexentry.itrace;
857  std::string formatID;
858  is >> formatID;
859  indexentry.dataformat=formatID;
860  // just skip EOL
861  getline(is, formatID);
862  indexentry.wid2.read(is);
863  if (opt.debug)
864  {
865  cout << " filename: " << indexentry.filename << endl;
866  cout << " trace #: " << indexentry.itrace << endl;
867  cout << " data format: " <<
868  indexentry.dataformat << endl;
869  cout << " " << indexentry.wid2.line();
870  }
871 
872  // then, check selection parameters
873  bool match=true;
874  if (opt.firstset)
875  { match=(opt.first<=sff::wid2lastsample(indexentry.wid2)); }
876  if (opt.lastset && match)
877  { match=(opt.last>=indexentry.wid2.date); }
878  if (match) { match=rgxx.station.match(indexentry.wid2.station); }
879  if (match) { match=rgxx.channel.match(indexentry.wid2.channel); }
880  if (match) { match=rgxx.instrument.match(indexentry.wid2.instype); }
881  if (match) { match=rgxx.auxid.match(indexentry.wid2.auxid); }
882 
883  if (match)
884  {
885  collection.push_back(indexentry);
886  if (opt.verbose)
887  {
888  cout << " match: " << indexentry << endl;
889  }
890  }
891 
892  // fill this field before reentering the loop
893  is >> indexentry.filename;
894  ++nscanned;
895  }
896  if (opt.verbose)
897  {
898  cout << " scanned " << nscanned << " entries in index file" << endl;
899  }
900  ++infile;
901  }
902  if (opt.verbose)
903  {
904  cout << "found " << collection.size() << " matching entries" << endl;
905  }
906 
907  /*----------------------------------------------------------------------*/
908  // stage 1 dump:
909  if (opt.dumpintermediateresults)
910  {
911  cout << endl;
912  cout << "DUMP stage 1 results: all matching entries" << endl;
913  Tvecofindexentries::const_iterator iv=collection.begin();
914  while(iv != collection.end())
915  {
916  const IndexEntry& entry= (*iv);
917  const sff::WID2& wid2=entry.wid2;
918  cout << " " << wid2.station
919  << " " << wid2.channel
920  << " " << wid2.auxid
921  << " " << wid2.instype
922  << " dt=" << wid2.dt << "s"
923  << " " << wid2.date.timestring().substr(4,23)
924  << " n=" << wid2.nsamples
925  << " " << entry.filename
926  << " #" << entry.itrace
927  << " " << entry.dataformat << endl;
928  ++iv;
929  }
930  cout << endl;
931  }
932 
933  /*======================================================================*/
934  /* 2. sort collection
935  *
936  * In this section the program scans the collection of index entries in the
937  * global variable
938  *
939  * Tvecofindexentries collection;
940  *
941  * The program compiles a set of links into the collection. The links are
942  * organized as follows:
943  *
944  * For each unique stream (defined by station, channel, sampling interval and
945  * auxid) a list of type Tintlist is created. The entries of this list
946  * refer to entries in the global collection in the order of increasing date
947  * of first sample. All these lists are collected in the global variable
948  *
949  * Tvecofintlist chain;
950  *
951  */
952  if (opt.verbose || opt.findgapsonly)
953  {
954  cout << endl;
955  cout << "step 2: sort collected index entries" << endl;
956  }
957 
958  // compare WID2
959  sff::WID2compare
960  equalstreams(sff::Fstation|sff::Fchannel|sff::Fdt|sff::Fauxid);
961 
962  // build vector of chains
963  if (opt.verbose) { cout << " fill raw chains" << endl; }
964  Tvecofintlist chain;
965  for (unsigned int ientry=0; ientry<collection.size(); ++ientry)
966  {
967  // if vector is empty, it's easy
968  if (chain.size()==0)
969  {
970  Tintlist newlist;
971  newlist.push_back(ientry);
972  chain.push_back(newlist);
973  }
974  else
975  {
976  // find matching
977  int imatch=-1;
978  for (unsigned int ilist=0; ilist<chain.size(); ++ilist)
979  {
980  if (equalstreams(collection[ientry].wid2,
981  collection[chain[ilist].front()].wid2))
982  { imatch=ilist; }
983  }
984  if (imatch<0)
985  {
986  // found no matching chain
987  Tintlist newlist;
988  newlist.push_back(ientry);
989  chain.push_back(newlist);
990  }
991  else
992  {
993  chain[imatch].push_back(ientry);
994  }
995  }
996  }
997 
998  // sort vector of chains
999  if (opt.verbose) { cout << " sort chain(s) for "
1000  << chain.size() << " unique stream(s)" << endl; }
1001  CompareCollection comparer(collection);
1002  for (unsigned int ilist=0; ilist<chain.size(); ++ilist)
1003  { chain[ilist].sort(comparer); }
1004 
1005  // tell result
1006  if (opt.verbose)
1007  {
1008  for (unsigned int ilist=0; ilist<chain.size(); ++ilist)
1009  {
1010  const Tintlist& thelist=chain[ilist];
1011  cout << " next stream:" << endl;
1012  const IndexEntry& entry=collection[thelist.front()];
1013  cout << " station: " << entry.wid2.station;
1014  cout << " channel: " << entry.wid2.channel;
1015  cout << " instrument: " << entry.wid2.instype;
1016  cout << " auxid: " << entry.wid2.auxid << endl;
1017  Tintlist::const_iterator iinlist=thelist.begin();
1018  while( iinlist!=thelist.end())
1019  {
1020  cout << " " << collection[*iinlist] << endl;
1021  sff::WID2 thewid2=collection[*iinlist].wid2;
1022  if (opt.debug)
1023  {
1024  cout << "DEBUG: "
1025  << collection[*iinlist].filename
1026  << " " << collection[*iinlist].itrace
1027  << " " << collection[*iinlist].dataformat << endl;
1028  cout << "DEBUG: " << thewid2.line();
1029  }
1030  cout << " " << thewid2.date.timestring()
1031  << " - " << sff::wid2lastsample(thewid2).timestring()
1032  << endl;
1033  ++iinlist;
1034  }
1035  }
1036  }
1037 
1038  /*----------------------------------------------------------------------*/
1039  // stage 2 dump:
1040  if (opt.dumpintermediateresults)
1041  {
1042  cout << endl;
1043  cout << "DUMP stage 2 results: chains for each channel" << endl;
1044  Tvecofintlist::const_iterator iv=chain.begin();
1045  while (iv != chain.end())
1046  {
1047  Tintlist::const_iterator il=iv->begin();
1048  const IndexEntry& head = collection[*il];
1049  const sff::WID2& hw2=head.wid2;
1050  cout << hw2.station
1051  << " " << hw2.channel
1052  << " " << hw2.auxid
1053  << " " << hw2.instype
1054  << " (dt=" << hw2.dt << "s):" << endl;
1055  while (il != iv->end())
1056  {
1057  const IndexEntry& entry = collection[*il];
1058  libtime::TAbsoluteTime lastdate=sff::wid2lastsample(entry.wid2);
1059  cout << " "
1060  << " #";
1061  cout.width(2);
1062  cout.fill('0');
1063  cout << *il << ": "
1064  << entry.wid2.date.timestring().substr(4,23) << " - "
1065  << lastdate.timestring().substr(4,23)
1066  << " (" << entry.filename
1067  << " #" << entry.itrace
1068  << " " << entry.dataformat
1069  << ")" << endl;
1070  ++il;
1071  }
1072  ++iv;
1073  }
1074  }
1075 
1076  /*======================================================================*/
1077  /* 3. setup traces
1078  *
1079  * In this section the program compiles continuous sets of data that
1080  * appear in the Tintlist elements in the global variable
1081  *
1082  * Tvecofintlist chain;
1083  *
1084  * Each continuous set of data may contain samples from one or more files.
1085  * These continuous sets are defined by variables of type Tvecofblocks which
1086  * are vectors of elements of type DataBlock. There is one entry of type
1087  * DataBlock for each file that contributes samples to the continuous set of
1088  * data. Within the DataBlock a copy operation is defined. Each copy
1089  * operation is defined by the source file (referenced by ientry, which is
1090  * the element index to the global collection), the first sample to read
1091  * (ifirst) from the input file and the sample this first value has to be
1092  * written to in the continuous set (ofirst), and the number of samples to
1093  * be copied (nsamples).
1094  *
1095  * These continuous sets of data are collected in the global variable
1096  *
1097  * Tvecoftraces trace;
1098  *
1099  */
1100  if (opt.verbose || opt.findgapsonly)
1101  {
1102  cout << endl;
1103  cout << "step 3: define copy operations" << endl;
1104  }
1105 
1106  // define a time span of zero length, for comparison
1107  // (will be modified later, if requested)
1108  libtime::TRelativeTime tolerancewindow(0);
1109  // set of traces to define
1110  Tvecoftraces trace;
1111 
1112  // cycle through vector of unique data streams
1113  // -------------------------------------------
1114  for (unsigned int ichain=0; ichain<chain.size(); ++ichain)
1115  {
1116  // new trace = vector of blocks
1117  Tvecofblocks block;
1118  // get reference to list that must be scanned next
1119  // each list contains links to all data from a specific stream (defined by
1120  // station, channel, instrument and auxid) within the requested time
1121  // interval
1122  const Tintlist& thelist=chain[ichain];
1123  if (opt.verbose)
1124  {
1125  IndexEntry &theentry(collection[thelist.front()]);
1126  cout << "scan chain for stream" << endl;
1127  cout << " * station: " << theentry.wid2.station;
1128  cout << " * channel: " << theentry.wid2.channel;
1129  cout << " * instrument: " << theentry.wid2.instype;
1130  cout << " * auxid: " << theentry.wid2.auxid;
1131  cout << " * dt=" << theentry.wid2.dt << "s" << endl;
1132  }
1133  // time of next sample
1134  libtime::TAbsoluteTime nextdate;
1135  // next output trace sample to continue with
1136  int nextosample=0;
1137  // keep track of streams
1138  bool newstream=true;
1139 
1140  // scan chain for this unique data stream
1141  // --------------------------------------
1142  Tintlist::const_iterator ilist=thelist.begin();
1143  while (ilist!=thelist.end())
1144  {
1145  // get reference to entry to work on
1146  const IndexEntry& entry=collection[*ilist];
1147 
1148  // report
1149  if (opt.verbose)
1150  {
1151  if (block.empty())
1152  {
1153  cout << " * begin a new output trace" << endl;
1154  }
1155  cout << " * process collection entry #" << *ilist << ": "
1156  << entry.filename << " "
1157  << entry.itrace << " "
1158  << entry.dataformat << endl;
1159  cout << " "
1160  << entry.wid2.date.timestring()
1161  << " - "
1162  << sff::wid2lastsample(entry.wid2).timestring() << endl;
1163  }
1164 
1165  // next block:
1166  // this must define a copy operation from a trace in a source file
1167  // to a destination trace
1168  DataBlock theblock;
1169  // link to entry in global collection
1170  // which is the links to the data source trace
1171  theblock.ientry= *ilist;
1172  // flag to indicate, that last sample selected (by time of last sample)
1173  // is already contained in data block
1174  bool complete=false;
1175 
1176  // in case of tolerance, adjust tolerancewindow
1177  if (opt.allowtolerance)
1178  {
1179  tolerancewindow
1180  =libtime::double2time(opt.relativetolerance*entry.wid2.dt);
1181  }
1182 
1183  // adjust date of next sample to extract if we start a new stream
1184  // or a new block (the latter only in case we allow duplicate samples)
1185  if (newstream || (block.empty() && opt.allowduplicatesamples))
1186  {
1187  // set nextdate to first sample requested, if appropriate
1188  if (opt.firstset && (opt.first > entry.wid2.date))
1189  {
1190  nextdate = opt.first;
1191  }
1192  // set to beginning of current entry otherwise
1193  else
1194  {
1195  nextdate = entry.wid2.date;
1196  }
1197  }
1198 
1199  /* the conditions for duplicate samples are (in relaxing order)
1200  *
1201  * 1. duplicate input samples are fatal (default)
1202  * 2. break chain on duplicate samples
1203  * 3. duplicate samples are allowed
1204  */
1205 
1206  // prepare partial GAP contitions
1207  bool gc_not_empty = (!block.empty());
1208  if (!gc_not_empty) { nextdate=entry.wid2.date; }
1209  bool gc_no_duplicates_allowed = (!opt.allowduplicatesamples);
1210  bool gc_raster_residual_exceeds_tolerance
1211  = (sff::wid2isamplerest(entry.wid2,nextdate) > tolerancewindow);
1212  long int gc_sample_index
1213  = sff::wid2isample(entry.wid2,nextdate);
1214  bool gc_sample_overlap = (gc_sample_index > 0);
1215  bool gc_sample_match = (gc_sample_index == 0);
1216  bool gc_sample_gap = (gc_sample_index < 0);
1217  bool gc_no_new_data = ((nextdate - tolerancewindow)
1218  > sff::wid2lastsample(entry.wid2));
1219  bool gc_break_on_duplicate = opt.breakonduplicatesamples;
1220 
1221  // report partial GAP conditions
1222  if (opt.debug)
1223  {
1224  cout << "DEBUG GAP conditions:" << endl;
1225  if (gc_not_empty)
1226  cout << "-1--- block is not empty" <<endl;
1227  if (gc_raster_residual_exceeds_tolerance)
1228  cout << "-2--- time raster residual exceeds tolerance" <<endl;
1229  if (gc_no_duplicates_allowed)
1230  cout << "-3--- duplicate samples are not allowed" << endl;
1231  if (gc_sample_overlap)
1232  cout << "-4--- sample windows overlap" << endl;
1233  if (gc_sample_match)
1234  cout << "-5--- sample windows match" << endl;
1235  if (gc_sample_gap)
1236  cout << "-6--- sample windows gap" << endl;
1237  cout << "----- sample index: " << gc_sample_index << endl;
1238  }
1239 
1240  // enter GAP conditional
1241  // ---------------------
1242  // this is a large block of conditionals, that distinguishes the
1243  // different cases of GAP and non-GAP conditions, we might meet here
1244 
1245  // handle GAP condition first
1246  if (gc_not_empty
1247  && (gc_sample_gap
1248  || gc_raster_residual_exceeds_tolerance
1249  || (gc_no_duplicates_allowed
1250  && gc_sample_overlap)))
1251  {
1252  // check fatal condition
1253  if (gc_sample_overlap
1254  && gc_no_duplicates_allowed
1255  && (!gc_break_on_duplicate))
1256  {
1257  cout << "duplicates: " << endl;
1258  cout << " next sample requested: "
1259  << nextdate.timestring() << endl;
1260  cout << " is later than first sample in input: "
1261  << entry.wid2.date.timestring() << endl;
1262  cout << " when processing entry" << endl;
1263  cout << entry << endl;
1264  TFXX_abort("ERROR: duplicate input samples are fatal!");
1265  }
1266  if (opt.verbose || opt.findgapsonly)
1267  {
1268  cout << "! GAP ("
1269  << entry.wid2.station << ","
1270  << entry.wid2.channel << ","
1271  << entry.wid2.auxid << "): ";
1272  if (nextdate < entry.wid2.date)
1273  {
1274  cout << nextdate.timestring() << " (expected)" << " < "
1275  << entry.wid2.date.timestring() << " (actual)" << endl;
1276  }
1277  else if ((entry.wid2.date <= nextdate) &&
1278  (sff::wid2isamplerest(entry.wid2,nextdate)
1279  > tolerancewindow))
1280  {
1281  cout << nextdate.timestring() << " (expected)" << " >= "
1282  << entry.wid2.date.timestring() << " (actual)" << endl
1283  << " && " << " "
1284  << sff::wid2isamplerest(entry.wid2,nextdate).timestring()
1285  << " (residual to sampling raster)"
1286  << " > " << tolerancewindow.timestring()
1287  << " (tolerance)" << endl;
1288  /*
1289  libtime::TRelativeTime diff=entry.wid2.date-nextdate;
1290  cout << "NOTICE: diff=" << diff.timestring()<< endl;
1291  libtime::TRelativeTime dt=libtime::double2time(entry.wid2.dt);
1292  cout << "NOTICE: dt=" << dt.timestring()<< endl;
1293  long int i=diff/dt;
1294  cout << "NOTICE: i=" << i<< endl;
1295  libtime::TRelativeTime ti=diff%dt;
1296  cout << "NOTICE: ti=" << ti.timestring()<< endl;
1297  */
1298  }
1299  else if (gc_sample_overlap && gc_no_duplicates_allowed)
1300  {
1301  cout << "duplicates: ";
1302  cout << nextdate.timestring() << " (expected)" << " > "
1303  << entry.wid2.date.timestring() << " (actual)" << endl;
1304  }
1305  else
1306  {
1307  TFXX_abort("ERROR: undefined condition for GAP!");
1308  }
1309  } // if (opt.verbose || opt.findgapsonly)
1310 
1311  // gap found: start new trace
1312  trace.push_back(block);
1313  // begin with new vector of blocks (new trace)
1314  block.clear();
1315  // begin with new trace
1316  nextosample=0;
1317  }
1318  // skip if file provides no new data
1319  else if (gc_no_new_data)
1320  {
1321  if (opt.verbose)
1322  {
1323  cout << " skip this (next requested: "
1324  << nextdate.timestring() << ")" << endl;
1325  }
1326  ++ilist;
1327  }
1328  // define copy operation for samples
1329  else
1330  {
1331  if (opt.verbose)
1332  {
1333  cout << " define copy (next requested: "
1334  << nextdate.timestring() << ")" << endl;
1335  }
1336  // remember value of next destination sample to use
1337  theblock.ofirst= nextosample;
1338  // default: first sample of source
1339  theblock.ifirst=0;
1340  // if first in block, find first to extract
1341  if (!block.empty())
1342  {
1343  TFXX_assert((entry.wid2.date <= (nextdate+tolerancewindow)),
1344  "ERROR: unexpected GAP(1): check program!");
1345  TFXX_assert((sff::wid2isamplerest(entry.wid2,nextdate)
1346  <= tolerancewindow),
1347  "ERROR: unexpected GAP(2): check program!");
1348  theblock.ifirst=sff::wid2isample(entry.wid2,nextdate);
1349  }
1350  else if (opt.firstset)
1351  {
1352  if (entry.wid2.date <= opt.first)
1353  { theblock.ifirst=sff::wid2isample(entry.wid2,opt.first); }
1354  }
1355  // calculate number of samples to read from input
1356  // if the last sample is within this block
1357  theblock.nsamples=entry.wid2.nsamples-theblock.ifirst;
1358  if (opt.lastset)
1359  {
1360  if (sff::wid2lastsample(entry.wid2)>opt.last)
1361  {
1362  theblock.nsamples=sff::wid2isample(entry.wid2,opt.last)-
1363  theblock.ifirst+1;
1364  complete=true;
1365  }
1366  }
1367  // set values to continue with next block
1368  nextosample += theblock.nsamples;
1369  nextdate=sff::wid2isample(entry.wid2,
1370  theblock.nsamples+
1371  theblock.ifirst);
1372  if (opt.verbose)
1373  {
1374  cout << " copy input samples "
1375  << theblock.ifirst << "-" << theblock.ifirst+theblock.nsamples-1
1376  << " to output samples "
1377  << theblock.ofirst << "-" << nextosample-1
1378  << "(" << theblock.ofirst+theblock.nsamples-1 << ")" << endl
1379  << " "
1380  << sff::wid2isample(entry.wid2,theblock.ifirst).timestring()
1381  << " - "
1382  << sff::wid2isample(entry.wid2,theblock.ifirst+
1383  theblock.nsamples-1).timestring()
1384  << endl;
1385  }
1386  // add this block to trace
1387  block.push_back(theblock);
1388  // if complete: add this trace to vector of traces
1389  if (complete)
1390  {
1391  if (opt.verbose)
1392  {
1393  cout << " * time window is complete" << endl;
1394  }
1395  trace.push_back(block);
1396  // begin with new vector of blocks (new trace)
1397  block.clear();
1398  // begin with new trace
1399  nextosample=0;
1400  } // if (complete)
1401  // next entry
1402  ++ilist;
1403  } // if: GAP or skip condition
1404  // the large contitional is finished
1405  // ---------------------------------
1406 
1407  // we finished the first entry in the chain for this data stream,
1408  // at least
1409  newstream=false;
1410 
1411  } // while (ilist!=thelist.end())
1412  // at this point all chain entries for this unique data stream are
1413  // scanned; go to next data stream
1414 
1415  // is there still a block to be finished?
1416  if (!block.empty())
1417  {
1418  if (opt.verbose)
1419  { cout << "! * time window can not be completed!" << endl; }
1420  trace.push_back(block);
1421  } // if (!block.empty())
1422 
1423  } // for (unsigned int ichain=0; ichain<chain.size(); ++ichain)
1424  // at this point all entries in the chains for all unique data streams
1425  // are in some way placed in the output copy definitions
1426 
1427  /*----------------------------------------------------------------------*/
1428  // stage 3 dump:
1429  if (opt.dumpintermediateresults)
1430  {
1431  cout << endl;
1432  cout << "DUMP stage 3 results: trace copy operations" << endl;
1433  Tvecoftraces::const_iterator iv=trace.begin();
1434  int itrace=0;
1435  while (iv != trace.end())
1436  {
1437  const Tvecofblocks& block= (*iv);
1438  Tvecofblocks::const_iterator ivb=block.begin();
1439  const IndexEntry& headentry = collection[ivb->ientry];
1440  const sff::WID2& wid2=headentry.wid2;
1441  cout << " #";
1442  cout.width(2);
1443  cout.fill('0');
1444  cout << ++itrace;
1445  cout << " " << wid2.station
1446  << " " << wid2.channel
1447  << " " << wid2.auxid
1448  << " " << wid2.instype
1449  << " dt=" << wid2.dt << "s"
1450  << endl;
1451  while (ivb != block.end())
1452  {
1453  const DataBlock& theblock = (*ivb);
1454  const IndexEntry& entry = collection[ivb->ientry];
1455  const sff::WID2& ew2=entry.wid2;
1456  long int lastinputsample=theblock.ifirst+theblock.nsamples-1;
1457  cout << " ";
1458  cout.width(5);
1459  cout << theblock.ifirst << "-";
1460  cout.width(5);
1461  cout << lastinputsample << " -> ";
1462  cout.width(6);
1463  cout << theblock.ofirst << "-";
1464  cout.width(6);
1465  cout << theblock.ofirst+theblock.nsamples-1;
1466  cout << " " << ew2.date.timestring().substr(4,23);
1467  cout << " - ";
1468  cout << sff::wid2isample(ew2,lastinputsample).timestring().substr(4,23);
1469  cout << endl;
1470  ++ivb;
1471  }
1472  ++iv;
1473  }
1474  cout << endl;
1475  }
1476 
1477  /*======================================================================*/
1478  /* stage 4
1479  *
1480  * distinguishes between data extraction mode (default) and gap finding
1481  *
1482  * First a file FREE block is set up reporting the parameters of data
1483  * selection. This block is also used to report to the user (not only to the
1484  * output data file).
1485  *
1486  * The code for stage is then divided into two large section by the very
1487  * first conditional. If doGAPanalysis is true several tasks for analyzing
1488  * the completeness of the input data as represented by the index entries
1489  * can be executed. The program finished then immediately without extracting
1490  * data. If not, data samples are actually extracted.
1491  */
1492 
1493  // prepare file free block and write
1494  sff::FREE filefree;
1495  filefree.append(ANYEXTRACT_VERSION);
1496  filefree.append("selection:");
1497  if (opt.firstset)
1498  {
1499  filefree.append(std::string("* first sample: ")+opt.first.timestring());
1500  }
1501  else
1502  {
1503  filefree.append(std::string("* first sample: any"));
1504  }
1505  if (opt.lastset)
1506  {
1507  filefree.append(std::string("* last sample: ")+opt.last.timestring());
1508  }
1509  else
1510  {
1511  filefree.append(std::string("* last sample: any"));
1512  }
1513  filefree.append(std::string("* station: ")+opt.selstation);
1514  filefree.append(std::string("* channel: ")+opt.selchannel);
1515  filefree.append(std::string("* instrument: ")+opt.selinstrument);
1516  filefree.append(std::string("* auxid: ")+opt.selauxid);
1517  if (opt.allowduplicatesamples)
1518  filefree.append("* duplicate input samples are tolerated");
1519  if (opt.breakonduplicatesamples)
1520  filefree.append("* duplicate input samples are a break condition");
1521  if (opt.allowtolerance)
1522  {
1523  std::ostringstream oss;
1524  oss << "* sampling raster tolerance is "
1525  << opt.relativetolerance
1526  << " of sampling interval";
1527  filefree.append(oss.str());
1528  }
1529 
1530  /* Conditional
1531  * -----------
1532  * distinguish between gap analysis and data extraction
1533  */
1534  if (doGAPanalysis)
1535  {
1536  /*======================================================================*/
1537  /* 4. gap analysis
1538  *
1539  * This block contains several tasks to analyse the completeness of the
1540  * data as being represented by the index entries previously read.
1541  *
1542  * a) Cycle through all traces defined for data output. These traces
1543  * actually reflect all chunks of contiguous data being present in the
1544  * input.
1545  * The result of this analysis is stored in contiguouslist. Input data
1546  * is reported immediately in verbose mode.
1547  * b) If analyzecompleteness is true, a vector of gaps (vecofgaps) is
1548  * prepared by function gaps as the base for testing data completeness.
1549  * The vector is reported immediately if requested (opt.printgaps).
1550  *
1551  * After that:
1552  * - for presenting a completeness or gaps series, a series of gaps is
1553  * produced from the vecofgaps
1554  * - a completeness series is just a transformation of the gap series
1555  * - is a gnuplot control file is required this is prepared first
1556  */
1557  if (opt.verbose || opt.findgapsonly)
1558  {
1559  cout << endl;
1560  cout << "step 4: report contiguous data" << endl;
1561  }
1562 
1563  // report selection in verbose mode
1564  // --------------------------------
1565  if (opt.verbose)
1566  {
1567  cout << filefree;
1568  } // if (opt.verbose)
1569 
1570  /*----------------------------------------------------------------------*/
1571 
1572  /* a) prepare collection of statistics
1573  * -----------------------------------
1574  */
1575  libtime::TAbsoluteTime earliesttime;
1576  libtime::TAbsoluteTime latesttime;
1577  TContiguouslist contiguouslist;
1578 
1579  if (opt.verbose || (opt.summarizelevel < 3))
1580  {
1581  cout << "chunks of contiguous data:" << std::endl;
1582  }
1583 
1584  bool analyzecompleteness=opt.printgaps
1585  || opt.writegapseries || opt.writecompleteness
1586  || opt.providegnuplotplot;
1587 
1588  // cycle through traces
1589  for (unsigned int itrace=0; itrace<trace.size(); ++itrace)
1590  {
1591  if (opt.verbose) { cout << "compile trace #" << itrace+1 << ":" << endl; }
1592  Tvecofblocks &thetrace(trace[itrace]);
1593  sff::FREE tracefree;
1594  sff::WID2 tracewid2;
1595  // prepare WID2 line
1596  tracewid2=collection[thetrace[0].ientry].wid2;
1597  tracewid2.date=sff::wid2isample(tracewid2,thetrace[0].ifirst);
1598 
1599  // prepare dataspace
1600  libtime::TRelativeTime dt=libtime::double2time(tracewid2.dt);
1601  libtime::TAbsoluteTime lastdate=tracewid2.date;
1602  long int totalsamples=0;
1603  for (unsigned int iblock=0; iblock<thetrace.size(); ++iblock)
1604  {
1605  totalsamples+=thetrace[iblock].nsamples;
1606  // increment last date; this is safe in cases, where the final value
1607  // of totalsamples would exceed the 4-byte int value range
1608  lastdate += dt*thetrace[iblock].nsamples;
1609  }
1610  tracewid2.nsamples=totalsamples;
1611 
1612  tracefree.append("data from:");
1613  for (unsigned int iblock=0; iblock<thetrace.size(); ++iblock)
1614  {
1615  DataBlock &theblock(thetrace[iblock]);
1616  IndexEntry &theentry(collection[theblock.ientry]);
1617  std::ostringstream freeline;
1618  freeline << theentry.filename <<
1619  " trace #" << theentry.itrace <<
1620  " format: " << theentry.dataformat;
1621  tracefree.append(freeline.str());
1622  }
1623  // report block
1624  if (opt.verbose || (opt.summarizelevel < 3))
1625  {
1626  cout << tracewid2.station << " " << tracewid2.channel << " "
1627  << tracewid2.auxid << " "
1628  << tracewid2.date.timestring().substr(4,26) << " - "
1629  << lastdate.timestring().substr(4,26) << std::endl;
1630  }
1631  // finished reading, write now
1632  if (opt.verbose)
1633  {
1634  cout << tracewid2;
1635  cout << tracefree;
1636  }
1637 
1638  /*----------------------------------------------------------------------*/
1639  // record statistics
1640 
1641  if (analyzecompleteness)
1642  {
1643  // initalize times or record time span and statistics
1644 
1645  /* adjust values times for earliest and latest sample being expected
1646  * input data: either they are explicitely defined by command line
1647  * parameters or take the earliest and latest sample being present in
1648  * any of the input streams
1649  */
1650  if (itrace==0)
1651  {
1652  if (opt.firstset)
1653  {
1654  earliesttime=opt.first;
1655  }
1656  else
1657  {
1658  earliesttime=tracewid2.date;
1659  }
1660  if (opt.lastset)
1661  {
1662  latesttime=opt.last;
1663  }
1664  else
1665  {
1666  latesttime=lastdate;
1667  }
1668  }
1669  else
1670  {
1671  if ((!opt.firstset) && (tracewid2.date < earliesttime))
1672  {
1673  earliesttime=tracewid2.date;
1674  }
1675  if ((!opt.lastset) && (lastdate > latesttime))
1676  {
1677  latesttime=lastdate;
1678  }
1679  }
1680 
1681  // record properties of this chunk of contiguous data
1682  Contiguous conti;
1683  conti.first=tracewid2.date;
1684  conti.last=lastdate;
1685  conti.dt=libtime::double2time(tracewid2.dt);
1686  conti.station=tracewid2.station;
1687  conti.channel=tracewid2.channel;
1688  conti.auxid=tracewid2.auxid;
1689  contiguouslist.push_back(conti);
1690  } // if (opt.writestatistics)
1691 
1692  } // for (unsigned int itrace=0; itrace<trace.size(); ++itrace)
1693 
1694  // A collection of all chunks of contiguous data is now present in
1695  // contiguouslist. This is the base of all further analyses.
1696 
1697  /*----------------------------------------------------------------------*/
1698  // any further gap analysis?
1699 
1700  if (analyzecompleteness)
1701  {
1702  TFXX_debug(opt.debug, "main",
1703  "analyze contiguouslist and create vector of gaps");
1704 
1705  /* b) create vector of gaps
1706  */
1707  Tvecofgaps vecofgaps=gaps(earliesttime, latesttime,
1708  contiguouslist, opt.debug);
1709 
1710  if (opt.printgaps)
1711  {
1712  if (opt.gapoutputfile!="-")
1713  {
1714  if (!opt.overwrite)
1715  {
1716  datrw::abort_if_exists(opt.gapoutputfile);
1717  }
1718  std::ofstream os(opt.gapoutputfile.c_str());
1719  printgaps(os, vecofgaps, earliesttime, latesttime,
1720  opt.summarizelevel);
1721  }
1722  else
1723  {
1724  std::cout << std::endl;
1725  printgaps(std::cout, vecofgaps, earliesttime, latesttime,
1726  opt.summarizelevel);
1727  }
1728  } // if (opt.printgaps)
1729 
1730  /*----------------------------------------------------------------------*/
1731  // produce gnuplot plot file
1732  if (opt.providegnuplotplot)
1733  {
1734  std::string gnuplotfile=opt.gnuplotfile+".gpt";
1735  if (!opt.overwrite)
1736  {
1737  datrw::abort_if_exists(gnuplotfile);
1738  }
1739  std::ofstream ofs(gnuplotfile.c_str());
1740  libtime::TRelativeTime binsize(opt.binsize);
1741  CompletenessBins cs(earliesttime,latesttime,binsize);
1742  gnuplotplot(ofs, opt.gnuplotfile+".ps", cs, vecofgaps);
1743  } // if (opt.providegnuplotplot)
1744 
1745  /*----------------------------------------------------------------------*/
1746  // write time series with gap information
1747  if (opt.writegapseries || opt.writecompleteness)
1748  {
1749  TFXX_debug(opt.debug, "main",
1750  "write gap and/or completeness series");
1751  std::ofstream* Pgofs;
1752  std::ofstream* Pcofs;
1753  datrw::oanystream* Pgos;
1754  datrw::oanystream* Pcos;
1755  if (opt.writegapseries)
1756  {
1757  if (!opt.overwrite)
1758  {
1759  datrw::abort_if_exists(opt.gapseriesfile);
1760  }
1761  Pgofs=new std::ofstream(opt.gapseriesfile.c_str(),
1762  datrw::oanystream::openmode(opt.outputformat));
1763  Pgos=new datrw::oanystream(*Pgofs, opt.outputformat, opt.debug);
1764  }
1765  if (opt.writecompleteness)
1766  {
1767  if (!opt.overwrite)
1768  {
1769  datrw::abort_if_exists(opt.completenessseriesfile);
1770  }
1771  Pcofs=new std::ofstream(opt.completenessseriesfile.c_str(),
1772  datrw::oanystream::openmode(opt.outputformat));
1773  Pcos=new datrw::oanystream(*Pcofs, opt.outputformat, opt.debug);
1774  }
1775  libtime::TRelativeTime binsize(opt.binsize);
1776  TFXX_debug(opt.debug, "main",
1777  "earliesttime: " << earliesttime.timestring()
1778  << " latesttime: " << latesttime.timestring());
1779  CompletenessBins completenessbins(earliesttime,latesttime,binsize);
1780  for (Tvecofgaps::const_iterator S=vecofgaps.begin();
1781  S!=vecofgaps.end(); ++S)
1782  {
1783  GapSeries gapseries=seriesofmissingsamples(*S, completenessbins,
1784  opt.debug);
1785  if (opt.writegapseries)
1786  {
1787  *Pgos << gapseries.header.wid2();
1788  *Pgos << gapseries.gapseries;
1789  }
1790  if (opt.writecompleteness)
1791  {
1792  CompletenessSeries cseries=completeness(gapseries, opt.debug);
1793  *Pcos << cseries.header.wid2();
1794  *Pcos << cseries.completeness;
1795  TFXX_debug(opt.debug, "main",
1796  "just wrote completeness time series with "
1797  << cseries.completeness.size()
1798  << " samples");
1799  }
1800  }
1801  if (opt.writegapseries)
1802  {
1803  delete Pgos;
1804  delete Pgofs;
1805  }
1806  if (opt.writecompleteness)
1807  {
1808  TFXX_debug(opt.debug, "main",
1809  "close completeness datstream");
1810  delete Pcos;
1811  TFXX_debug(opt.debug, "main",
1812  "close completeness file stream");
1813  delete Pcofs;
1814  }
1815  } // if (opt.writegapseries || opt.writecompleteness)
1816  } // if (analyzecompleteness)
1817 
1818  } // if (doGAPanalysis)
1819  else
1820  {
1821  /*======================================================================*/
1822  /* 4. copy data
1823  *
1824  * In this last section the program cycles through all sets of continuous
1825  * data that are defined in the global variable
1826  *
1827  * Tvecoftraces trace;
1828  *
1829  * Each element in the global variable trace defines a trace in the output
1830  * file of the program. For each of these traces a time series is compiled
1831  * from the input files as defined by the copy operations specified by the
1832  * DataBlock elements for each trace.
1833  *
1834  * Data files are only read and written within this last section of the
1835  * program.
1836  */
1837  if (opt.verbose)
1838  {
1839  cout << endl;
1840  cout << "step 4: copy data" << endl;
1841  if (opt.integerdata)
1842  { cout << "extract integer samples" << endl; }
1843  if (opt.GSEoutput)
1844  { cout << "write SFF with GSE compatible scaling (ampfac)" << endl; }
1845  }
1846 
1847  // open output file
1848  if (opt.verbose) { cout << "open output file " << outfile << endl; }
1849  // check if output file exists and open
1850  if (!opt.overwrite) { datrw::abort_if_exists(outfile); }
1851  std::ofstream ofs(outfile.c_str(),
1852  datrw::oanystream::openmode(opt.outputformat));
1853  datrw::oanystream os(ofs, opt.outputformat, opt.debug);
1854 
1855  filefree.append("index file(s):");
1856  infile=infiles.begin();
1857  while( infile!=infiles.end()) { filefree.append(*infile); ++infile; }
1858  if ((!opt.nofreeblock) && os.handlesfilefree()) { os << filefree; }
1859  if (opt.debug) { cout << "DEBUG: file FREE block:" << endl << filefree; }
1860 
1861  // creater the sequential trace reader
1862  datrw::sequentialtracereader is(opt.debug);
1863  // cycle through traces
1864  for (unsigned int itrace=0; itrace<trace.size(); ++itrace)
1865  {
1866  if (opt.verbose) { cout << "compile trace #" << itrace+1 << ":" << endl; }
1867  // prepare dataspace
1868  Tvecofblocks &thetrace(trace[itrace]);
1869  int totalsamples=0;
1870  for (unsigned int iblock=0; iblock<thetrace.size(); ++iblock)
1871  {
1872  totalsamples+=thetrace[iblock].nsamples;
1873  }
1874  if (opt.debug)
1875  { cout << " extract " << totalsamples << " samples" << endl; }
1876  sff::FREE tracefree;
1877  sff::INFO traceinfo;
1878  bool hasinfo=false;
1879  sff::WID2 tracewid2;
1880  // prepare two flavours of time series containers
1881  Series tracedata;
1882  // set the right one to the appropriate size
1883  if (opt.integerdata)
1884  {
1885  TFXX_debug(opt.debug, "anyextract",
1886  "allocate integer data series");
1887  tracedata.is()=Series::Tis(totalsamples);
1888  tracefree.append("copy integer data");
1889  }
1890  else if (opt.floatdata)
1891  {
1892  TFXX_debug(opt.debug, "anyextract",
1893  "allocate float data series");
1894  tracedata.fs()=Series::Tfs(totalsamples);
1895  tracefree.append("copy float (single precision) data");
1896  }
1897  else
1898  {
1899  TFXX_debug(opt.debug, "anyextract",
1900  "allocate double data series");
1901  tracedata.ds()=Series::Tds(totalsamples);
1902  tracefree.append("copy double precision data");
1903  }
1904  TFXX_debug(opt.debug, "anyextract",
1905  "output series container is allocated");
1906 
1907  // prepare WID2 line
1908  tracewid2=collection[thetrace[0].ientry].wid2;
1909  tracewid2.nsamples=totalsamples;
1910  tracewid2.date=sff::wid2isample(tracewid2,thetrace[0].ifirst);
1911 
1912  tracefree.append("read data from:");
1913  for (unsigned int iblock=0; iblock<thetrace.size(); ++iblock)
1914  {
1915  DataBlock &theblock(thetrace[iblock]);
1916  IndexEntry &theentry(collection[theblock.ientry]);
1917  std::ostringstream freeline;
1918  freeline << theentry.filename <<
1919  " trace #" << theentry.itrace <<
1920  " format: " << theentry.dataformat;
1921  tracefree.append(freeline.str());
1922 
1923  // open data file and read samples
1924  if (opt.verbose)
1925  {
1926  cout << " open input file " << theentry.filename
1927  << " (mode: " << theentry.dataformat << ", "
1928  << "trace: " << theentry.itrace << ")"
1929  << endl;
1930  }
1931  is.select(theentry.filename, theentry.itrace,
1932  theentry.dataformat);
1933  Series inseries;
1934  TFXX_assert(is.good(), "ERROR: input is not good!");
1935  if (opt.integerdata)
1936  {
1937  TFXX_assert(is.providesi(),
1938  "ERROR: integer data requested\n"
1939  "but not provided by input stream");
1940  is >> inseries.is();
1941  }
1942  else if (opt.floatdata)
1943  {
1944  TFXX_assert(is.providesf(),
1945  "ERROR: float data requested\n"
1946  "but not provided by input stream");
1947  is >> inseries.fs();
1948  }
1949  else
1950  {
1951  TFXX_assert(is.providesd(),
1952  "ERROR: double precision data requested\n"
1953  "but not provided by input stream");
1954  is >> inseries.ds();
1955  }
1956  TFXX_assert(((theblock.ifirst+theblock.nsamples-1)
1957  <= int(inseries.last())),
1958  "ERROR: too few samples in input data!");
1959  TFXX_assert((theblock.ifirst >= int(inseries.first())),
1960  "ERROR: range error in input data!");
1961  TFXX_assert(((theblock.ofirst+theblock.nsamples-1)
1962  <= int(tracedata.last())),
1963  "ERROR: too few samples reserved in output data!");
1964  TFXX_assert((theblock.ofirst >= int(tracedata.first())),
1965  "ERROR: range error in output data!");
1966  for (int isample=0; isample<theblock.nsamples; ++isample)
1967  {
1968  int ioutsample=isample+theblock.ofirst;
1969  int iinsample=isample+theblock.ifirst;
1970  if (opt.rangecheck)
1971  {
1972  TFXX_assert(((ioutsample>=tracedata.first())
1973  &&(ioutsample<=tracedata.last())
1974  &&(iinsample>=inseries.first())
1975  &&(iinsample<=inseries.last())),
1976  "ERROR: series index out of range!");
1977  }
1978  if (opt.integerdata)
1979  { tracedata.is()(ioutsample)=inseries.is()(iinsample); }
1980  else if (opt.floatdata)
1981  { tracedata.fs()(ioutsample)=inseries.fs()(iinsample); }
1982  else
1983  { tracedata.ds()(ioutsample)=inseries.ds()(iinsample); }
1984  }
1985  // extract INFO line if first file has INFO
1986  if ((iblock == 0) && (is.hasinfo()))
1987  { is >> traceinfo; hasinfo=true; }
1988  }
1989  // adjust calib and calper if requested
1990  if (opt.setcalib) { tracewid2.calib=opt.newcalib; }
1991  if (opt.setcalper) { tracewid2.calper=opt.newcalper; }
1992  // finished reading, write now
1993  if (opt.verbose) { cout << " write output trace" << endl; }
1994  os << tracewid2;
1995  if ((!opt.nofreeblock) && os.handlestracefree()) { os << tracefree; }
1996  if (hasinfo && os.handlesinfo()) { os << traceinfo; }
1997  if (opt.integerdata)
1998  {
1999  os << tracedata.is();
2000  }
2001  else if (opt.floatdata)
2002  {
2003  os << tracedata.fs();
2004  }
2005  else
2006  {
2007  os << tracedata.ds();
2008  }
2009  }
2010  } // if not (doGAPanalysis)
2011 }
2012 
2013 /* ----- END OF anyextract.cc ----- */
Tgapseries gapseries
GapSeriesHeader header
libtime::TRelativeTime dt
int nsamples
Definition: anyextract.cc:337
Tds Mds
Definition: anyextract.cc:225
Tvecofgaps gaps(const libtime::TAbsoluteTime &earliest, const libtime::TAbsoluteTime &latest, const TContiguouslist &cl, const bool &debug)
Definition: fngaps.cc:47
a class to hold a gap series for one stream
struct to hold regular expressions.
Definition: anyextract.cc:261
std::string gapoutputfile
Definition: anyextract.cc:139
structs used in primary gap analysis (prototypes)
std::vector< IndexEntry > Tvecofindexentries
a vector of index entries
Definition: anyextract.cc:253
bool providegnuplotplot
Definition: anyextract.cc:142
std::vector< Tvecofblocks > Tvecoftraces
vector of vector of blocks.
Definition: anyextract.cc:352
Tds & ds()
Definition: anyextract.cc:176
class to define completenessbins (prototypes)
datrw::Tdseries Tseries
Definition: anyextract.cc:158
bool writegapseries
Definition: anyextract.cc:134
std::string selauxid
Definition: anyextract.cc:125
bool floatdata
Definition: anyextract.cc:118
bool printgaps
Definition: anyextract.cc:138
struct to hold index values defining a data block within a trace.
Definition: anyextract.cc:329
GapSeries seriesofmissingsamples(const Gapsofstream &gos, const CompletenessBins &cb, const bool &debug)
Function to extract a GapSeries from given Gapsofstream.
class to define the time axis of the completeness time series.
::sff::WID2 wid2() const
produce a WID2 header for file output
class to handle two different flavours of data
Definition: anyextract.cc:165
bool dumpintermediateresults
Definition: anyextract.cc:127
CompareCollection(const Tvecofindexentries &collection)
Definition: anyextract.cc:293
const Tvecofindexentries & Mcollection
Definition: anyextract.cc:298
struct to hold an index file entry.
Definition: anyextract.cc:241
bool allowduplicatesamples
Definition: anyextract.cc:128
bool selected() const
Definition: anyextract.cc:175
bool Mselectf
Definition: anyextract.cc:223
std::string completenessseriesfile
Definition: anyextract.cc:137
Tshape shape() const
Definition: anyextract.cc:200
libtime::TAbsoluteTime first
Definition: anyextract.cc:119
Tiseries Tis
Definition: anyextract.cc:168
datrw::Tfseries Tfseries
Definition: anyextract.cc:159
A comparison function class for the collection.
Definition: anyextract.cc:291
tfxx::string::regexx instrument
Definition: anyextract.cc:264
datrw::Tdseries Tseries
Definition: any2sff.cc:64
bool breakonduplicatesamples
Definition: anyextract.cc:129
libtime::TAbsoluteTime first
std::string selchannel
Definition: anyextract.cc:123
bool overwrite
Definition: any2any.cc:57
bool GSEoutput
Definition: anyextract.cc:118
CompletenessSeries completeness(const GapSeries &gs, const bool &debug)
convert gaps to completeness
bool writecompleteness
Definition: anyextract.cc:136
std::string outputformat
Definition: any2any.cc:59
double newcalib
Definition: anyextract.cc:133
std::vector< Tintlist > Tvecofintlist
vector of lists list of collections.
Definition: anyextract.cc:283
std::list< int > Tintlist
list of links to collection entries, building a chain for one channel.
Definition: anyextract.cc:277
std::string dataformat
Definition: anyextract.cc:247
tfxx::string::regexx channel
Definition: anyextract.cc:263
Tindex last() const
Definition: anyextract.cc:215
Indicate a contiguous set of data.
std::string selinstrument
Definition: anyextract.cc:124
Tfseries Tfs
Definition: anyextract.cc:169
Tis Mis
Definition: anyextract.cc:227
std::string gapseriesfile
Definition: anyextract.cc:135
int main(int iargc, char *argv[])
Definition: anyextract.cc:358
bool debug
Definition: any2any.cc:57
tfxx::string::regexx auxid
Definition: anyextract.cc:265
bool lastset
Definition: anyextract.cc:121
double newcalper
Definition: anyextract.cc:133
unsigned int summarizelevel
Definition: anyextract.cc:141
Tis::Tshape Tshape
Definition: anyextract.cc:172
Tfs & fs()
Definition: anyextract.cc:184
bool integerdata
Definition: any2ascii.cc:67
bool Mselecti
Definition: anyextract.cc:219
std::string channel
std::string filename
Definition: anyextract.cc:243
Tis & is()
Definition: anyextract.cc:192
#define ANYEXTRACT_VERSION
Definition: anyextract.cc:88
bool verbose
Definition: any2any.cc:57
std::string gnuplotfile
Definition: anyextract.cc:143
datrw::Tiseries Tiseries
Definition: anyextract.cc:160
bool setcalib
Definition: anyextract.cc:131
std::vector< std::string > Tvecofstrings
Definition: anyextract.cc:154
bool setcalper
Definition: anyextract.cc:132
Tfs Mfs
Definition: anyextract.cc:229
a class to hold a completeness series for one stream
tfxx::string::regexx station
Definition: anyextract.cc:262
bool Mselectd
Definition: anyextract.cc:221
bool rangecheck
Definition: anyextract.cc:117
std::list< Contiguous > TContiguouslist
A list to store information on all sequences of contiguous data.
Tindex first() const
Definition: anyextract.cc:213
std::vector< Gapsofstream > Tvecofgaps
vector to hold all gaps
aff::Tsubscript Tindex
Definition: anyextract.cc:170
std::string selstation
Definition: anyextract.cc:122
GapSeriesHeader header
Tseries Tds
Definition: anyextract.cc:167
bool findgapsonly
Definition: anyextract.cc:127
bool allowtolerance
Definition: anyextract.cc:128
std::string auxid
std::vector< DataBlock > Tvecofblocks
vector of blocks.
Definition: anyextract.cc:344
bool nofreeblock
Definition: anyextract.cc:118
void gnuplotplot(std::ostream &os, const std::string &psname, const CompletenessBins &cb, const Tvecofgaps &vog)
std::vector< std::string > Tvecofstrings
Definition: any2sff.cc:62
aff::Tsize Tsize
Definition: anyextract.cc:171
bool operator()(const int &i1, const int &i2)
Definition: anyextract.cc:295
libtime::TAbsoluteTime last
Definition: anyextract.cc:120
void printgaps(std::ostream &os, const Tvecofgaps &vog, const libtime::TAbsoluteTime &earliest, const libtime::TAbsoluteTime &latest, const unsigned int &lev)
Definition: fnprintgaps.cc:46
std::ostream & operator<<(std::ostream &os, const IndexEntry &entry)
output operator to report an index entry
Definition: anyextract.cc:304
all structs use to produce series of gaps and series of completeness (prototypes) ...
sff::WID2 wid2
Definition: anyextract.cc:249
function prototypes used in gap analysis (prototypes)
std::string binsize
Definition: anyextract.cc:140
std::string station
libtime::TAbsoluteTime last
bool firstset
Definition: anyextract.cc:121
double relativetolerance
Definition: anyextract.cc:130
Tcompletenessseries completeness