DATRW++ library: seismic data I/O with multiple formats

◆ main()

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

Definition at line 57 of file mseedtest.cc.

References datrw::mseed::SEED::ascii, datrw::mseed::SEED::SteimFrame::blocksize, datrw::mseed::SEED::DataOnlySEEDBlockette::bytesex, datrw::util::cpu(), datrw::util::cpu_Intel, datrw::util::cpu_unknown, datrw::mseed::key::data, DATRW_assert, datrw::hpmo::dt(), datrw::mseed::SEED::dump(), datrw::mseed::SEED::DataOnlySEEDBlockette::format, datrw::mseed::SEED::DataExtensionBlockette::ifcount(), datrw::mseed::Debug::inconsistencies_are_not_fatal, MSEEDTEST_VERSION, datrw::mseed::needswap(), datrw::mseed::key::nframes, datrw::mseed::SEED::DataOnlySEEDBlockette::reclenbytes(), datrw::mseed::MiniSEEDblock::standard_block_size, datrw::mseed::SEED::steim1, and datrw::mseed::SEED::steim2.

58 {
59 
60  // define usage information
61  char usage_text[]=
62  {
64  "usage: mseedtest [-v] [-raw] [-reader] [-skip] [-stream] [-silent]" "\n"
65  " [-nfinconsist] [-dumpsamples] [-modifiers m]" "\n"
66  " [-logdump]\n"
67  " file [file...]" "\n"
68  " or: mseedtest --help|-h" "\n"
69  };
70 
71  // define full help text
72  char help_text[]=
73  {
74  "-v verbose mode" "\n"
75  "-raw Use raw reading functions from mseedstruct." "\n"
76  " This option uses an algorithm coded on mseedtest.cc\n"
77  " Tested conditions may be different from the conditions\n"
78  " tested in the actual reader functions in the library.\n"
79  " Being able to read a file with this option does not\n"
80  " necessarily mean, that the reader will decode the file\n"
81  " without complaining.\n"
82  "-reader use reading functions from mseedread" "\n"
83  "-skip skip data samples" "\n"
84  "-stream read data through stream" "\n"
85  "-generic use generic frame dump during raw test" "\n"
86  "-nfinconsist make inconsistencies non fatal errors" "\n"
87  "-dumpsamples dump sample values in reader mode" "\n"
88  "-modifiers m format modifiers" "\n"
89  "-silent be silent in stream mode; just output by imseedstream\n"
90  " is produced; this is useful to dump ASCII log entries\n"
91  "-logdump dump ASCII log entries\n"
92  " This is identical to\n"
93  " -stream -modifiers dumpascii -silent -skip\n"
94  };
95 
96  // define commandline options
97  using namespace tfxx::cmdline;
98  static Declare options[]=
99  {
100  // 0: print help
101  {"help",arg_no,"-"},
102  // 1: verbose mode
103  {"v",arg_no,"-"},
104  // 2: raw mode
105  {"raw",arg_no,"-"},
106  // 3: reader mode
107  {"reader",arg_no,"-"},
108  // 4: skip mode
109  {"skip",arg_no,"-"},
110  // 5: stream mode
111  {"stream",arg_no,"-"},
112  // 6: stream mode
113  {"generic",arg_no,"-"},
114  // 7: stream mode
115  {"nfinconsist",arg_no,"-"},
116  // 8: dump samples in reader mode
117  {"dumpsamples",arg_no,"-"},
118  // 9: dump samples in reader mode
119  {"modifiers",arg_yes,""},
120  // 10: dump samples in reader mode
121  {"silent",arg_no,"-"},
122  // 11: dump samples in reader mode
123  {"logdump",arg_no,"-"},
124  {NULL}
125  };
126 
127  // no arguments? print usage...
128  if (iargc<2)
129  {
130  cerr << usage_text << endl;
131  exit(0);
132  }
133 
134  // collect options from commandline
135  Commandline cmdline(iargc, argv, options);
136 
137  // help requested? print full help text...
138  if (cmdline.optset(0))
139  {
140  cerr << usage_text << endl;
141  cerr << help_text << endl;
142  exit(0);
143  }
144 
145  // dummy operation: print option settings
146  /*
147  for (int iopt=0; iopt<2; iopt++)
148  {
149  cout << "option: '" << options[iopt].opt_string << "'" << endl;
150  if (cmdline.optset(iopt)) { cout << " option was set"; }
151  else { cout << "option was not set"; }
152  cout << endl;
153  cout << " argument (string): '" << cmdline.string_arg(iopt) << "'" << endl;
154  cout << " argument (int): '" << cmdline.int_arg(iopt) << "'" << endl;
155  cout << " argument (long): '" << cmdline.long_arg(iopt) << "'" << endl;
156  cout << " argument (float): '" << cmdline.float_arg(iopt) << "'" << endl;
157  cout << " argument (double): '" << cmdline.double_arg(iopt) << "'" << endl;
158  cout << " argument (bool): '";
159  if (cmdline.bool_arg(iopt))
160  { cout << "true"; } else { cout << "false"; }
161  cout << "'" << endl;
162  }
163  */
164 
165  bool verbosemode=cmdline.optset(1);
166  bool rawmode=cmdline.optset(2);
167  bool readermode=cmdline.optset(3);
168  bool skipmode=cmdline.optset(4);
169  bool streammode=cmdline.optset(5);
170  bool genericframedump=cmdline.optset(6);
171 
172  datrw::mseed::Debug MiniSEEDdebug;
173  MiniSEEDdebug.inconsistencies_are_not_fatal=cmdline.optset(7);
174 
175  bool dumpsamples=cmdline.optset(8);
176  std::string modifiers=cmdline.string_arg(9);
177  bool silent=cmdline.optset(10);
178 
179  if (cmdline.optset(11))
180  {
181  modifiers="dumpascii";
182  silent=true;
183  streammode=true;
184  skipmode=true;
185  }
186 
187  if (verbosemode)
188  {
189  cout << MSEEDTEST_VERSION << endl;
190  cout << "in verbose mode" << endl;
191  }
192  if (MiniSEEDdebug.inconsistencies_are_not_fatal)
193  { cout << "inconsistencies are made non fatal" << endl; }
194 
195  while (cmdline.extra())
196  {
197  std::cout << std::endl;
198  std::string filename=cmdline.next();
199  std::cout << "file: " << filename << std::endl;
200  std::cout << "using standard input block size of "
202  << " bytes" << endl;
203 
204  /*======================================================================*/
205 
206  if (rawmode)
207  {
208  cout << endl;
209  cout << "raw mode" << endl;
210  cout << "========" << endl;
211 
212  std::ifstream ifs(filename.c_str());
213  int iblock=0;
214  int irecord=0;
216  ifs >> block;
217  while (ifs.good())
218  {
219  iblock++;
220  cout << endl << "BLOCK #" << iblock << endl
221  << "===========" << endl;
222  // SEED defines Motorola (big-endian) to be the standard byte order
223  // for all headers
224  // check our CPU type
227  "ERROR (reading MiniSEED record): "
228  "cannot identify CPU type");
229  bool doswap = (mysex == tfxx::ioswap::cpu_Intel);
230  if (doswap) { cout << "swap bytes, when reading header" << endl; }
231  else { cout << "do not swap bytes, when reading header" << endl; }
232  datrw::mseed::SEED::ControlHeader controlheader(block.block());
233  if ((controlheader.type == 'D')
234  || (controlheader.type == 'R')
235  || (controlheader.type == 'Q')
236  || (controlheader.type == 'M'))
237  {
239  dataheader(block.block(),doswap);
240  if (dataheader.fblock > block.bytesize())
241  {
242  // try it the other way
243  cout << "Could not find first Blockette!" << endl;
244  cout << "Trying different byte order..." << endl;
245  doswap = !doswap;
246  dataheader=datrw::mseed::SEED::FixedDataRecordHeader(block.block(),
247  doswap);
248  DATRW_assert((dataheader.fblock < block.bytesize()),
249  "ERROR (reading MiniSEED record): "
250  "cannot find first blockette");
251  cout << "Apparently we are reading raw data written by an "
252  << "EarthDataLogger (EDL) :-)" << endl;
253  if (doswap) { cout << "Hence"; }
254  else { cout << "Hence do not"; }
255  cout << " swap bytes, when reading header!" << endl;
256  }
257  ++irecord;
258  cout << endl;
259  cout << "RECORD #" << irecord << endl;
260  cout << "===========" << endl;
261  datrw::mseed::SEED::dump(dataheader, cout);
262  int nblockettes(dataheader.numblock);
263  unsigned int blocketteadr(dataheader.fblock);
264  // scan blockettes
265  bool foundBlockette1000=false;
266  bool foundBlockette1001=false;
269  for (int i=0; i<nblockettes; i++)
270  {
272  bh(block.block(blocketteadr), doswap);
273  cout << "Blockette #" << i<< endl;
274  if (bh.type == 1000)
275  {
277  bck(block.block(blocketteadr), doswap);
278  datrw::mseed::SEED::dump(bck, cout);
279  blockette1000=bck;
280  foundBlockette1000=true;
281  }
282  else if (bh.type == 1001)
283  {
285  bck(block.block(blocketteadr), doswap);
286  datrw::mseed::SEED::dump(bck, cout);
287  blockette1001=bck;
288  foundBlockette1001=true;
289  }
290  else
291  {
292  datrw::mseed::SEED::dump(bh, cout);
293  }
294  blocketteadr=bh.next;
295  }
296  // prepare frame reading
297  if (foundBlockette1000)
298  {
299  // For SEED data (not header fields) the byte order my differ from
300  // file to file. Use the byte order defined in the Data Only SEED
301  // Blockette.
302  bool dodataswap=datrw::mseed::needswap(blockette1000.bytesex);
303  if (!dodataswap) { cout << "do not "; }
304  cout << "swap bytes, when reading data" << endl;
305  if ((blockette1000.format == datrw::mseed::SEED::steim1) ||
306  (blockette1000.format == datrw::mseed::SEED::steim2))
307  {
308  unsigned int isamples=0;
309  int nframes=(blockette1000.reclenbytes()-dataheader.dbeg)/
311  cout << "total number of possible frames in record: "
312  << nframes << endl;
313  if (foundBlockette1001)
314  {
315  /*
316  cerr.flush();
317  cout.flush();
318  cout << "nframes: " << nframes << std::endl;
319  cout << "blockette1001.fcount: "
320  << blockette1001.ifcount() << std::endl;
321  cout << "blockette1000.reclenbytes:"
322  << blockette1000.reclenbytes() << std::endl;
323  cout << "dataheader.dbeg:"
324  << dataheader.dbeg << std::endl;
325  cout << "datrw::mseed::SEED::Steim1Frame::blocksize:"
326  << datrw::mseed::SEED::Steim1Frame::blocksize << std::endl;
327  */
328  /*
329  DATRW_assert((nframes == blockette1001.ifcount()),
330  "unexpected number of frames");
331  */
332  cout << "number of frames specified in Blockette 1001: "
333  << blockette1001.ifcount() << endl;
334  }
335  // read frames
336  unsigned int pframe=dataheader.dbeg;
337  for (unsigned int i=0; int(i)<nframes; ++i)
338  {
339  if (pframe >= block.bytesize())
340  {
341  ifs >> block;
342  pframe=0;
343  iblock++;
344  cout << endl << "BLOCK #" << iblock << endl
345  << "===========" << endl;
346  }
347  if (isamples < dataheader.nsamp)
348  { cout << "decode"; }
349  else { cout << "ignore"; }
350  cout << " frame #" << i+1 << "/" << nframes;
351  cout << " at 0x";
352  std::ostream::fmtflags flags=cout.flags();
353  cout.setf(std::ios_base::hex, std::ios_base::basefield);
354  // cout.setf(std::ios_base::showbase);
355  cout.width(4);
356  cout.fill('0');
357  cout << pframe;
358  cout.flags(flags);
359  cout << std::endl;
360  if (isamples < dataheader.nsamp)
361  {
362  if (blockette1000.format == datrw::mseed::SEED::steim1)
363  {
364  datrw::mseed::SEED::Steim1Frame frame(block.block(pframe),
365  dodataswap);
366  if (genericframedump)
367  {
368  datrw::mseed::SEED::SteimFrame& gframe=frame;
369  datrw::mseed::SEED::dump(gframe, cout);
370  }
371  else
372  {
373  datrw::mseed::SEED::dump(frame, cout);
374  }
375  frame.reset();
376  while (frame.valid())
377  {
378  ++isamples;
379  frame.next();
380  }
381  }
382  else
383  {
384  datrw::mseed::SEED::Steim2Frame frame(block.block(pframe),
385  dodataswap);
386  if (genericframedump)
387  {
388  datrw::mseed::SEED::SteimFrame& gframe=frame;
389  datrw::mseed::SEED::dump(gframe, cout);
390  }
391  else
392  {
393  datrw::mseed::SEED::dump(frame, cout);
394  }
395  frame.reset();
396  while (frame.valid())
397  {
398  ++isamples;
399  frame.next();
400  }
401  }
402  }
404  }
405  }
406  else if (blockette1000.format == datrw::mseed::SEED::ascii)
407  {
408  cout << "This is an ascii record" << endl;
409  unsigned int totalreclen=blockette1000.reclenbytes();
410  cout << "Provides " << totalreclen
411  << " bytes of data in total" << endl;
412  unsigned int bytecount=dataheader.dbeg;
413  unsigned int pframe=dataheader.dbeg;
414  cout << ">>";
415  while (bytecount < totalreclen)
416  {
417  if (pframe >= block.bytesize())
418  {
419  ifs >> block;
420  pframe=0;
421  iblock++;
422  cout << endl << "BLOCK #" << iblock << endl
423  << "===========" << endl;
424  }
425  while (pframe < block.bytesize())
426  {
427  char c=block[pframe];
428  if (isprint(c))
429  {
430  cout << c;
431  }
432  else if (c == 0x0d)
433  {
434  cout << endl << ">>";
435  }
436  ++pframe;
437  ++bytecount;
438  }
439  }
440  cout << endl;
441  }
442  else
443  {
444  cout << "Not steim1, steim2, or ascii format!" << std::endl;
445  }
446  }
447  else
448  {
449  cout << "No Blockette 1000 available!" << std::endl;
450  }
451  }
452  else
453  {
454  std::string seqnum(controlheader.seqno, 6);
455  cout << "seqno: #" << seqnum << "#"
456  << controlheader.type
457  << "-"
458  << controlheader.cont
459  << endl;
460  datrw::mseed::SEED::dump(controlheader, cout);
461  }
462  ifs >> block;
463  }
464  } // end raw mode
465 
466  /*======================================================================*/
467 
468  if (readermode)
469  {
470  cout << endl;
471  cout << "reader mode" << endl;
472  cout << "===========" << endl;
473 
474  std::ifstream ifs(filename.c_str());
475  datrw::mseed::MiniSEEDRecord record(MiniSEEDdebug);
476  int irecord=0;
477  while (ifs.good())
478  {
479  ++irecord;
480  cout << endl;
481  cout << "RECORD #" << irecord << endl;
482  cout << "===========" << endl;
483  if (skipmode)
484  {
485  if (verbosemode) { cout << "read record by skipping samples" << endl; }
486  record.skipdata(ifs);
487  }
488  else
489  {
490  if (verbosemode) { cout << "read record header and samples" << endl; }
491  ifs >> record;
492  }
493  if (record.valid())
494  {
495  if (!skipmode)
496  {
497  cout << " last sample of previous record: "
498  << record.xm1() << endl << endl;
499  }
500  datrw::mseed::SEED::dump(record.recordheader(), cout);
501  cout << endl;
502  datrw::mseed::SEED::dump(record.blockette1000(), cout);
503  cout << endl;
504  if (record.hasblockette1001())
505  {
506  datrw::mseed::SEED::dump(record.blockette1001(), cout);
507  cout << endl;
508  }
509  if (!skipmode)
510  {
511  cout << "data:" << endl;
513  cout << " number of samples in data: "
514  << data.size() << endl;
515  cout << " last sample of previous record: "
516  << record.xm1() << endl;
517  cout << " first sample: "
518  << data(data.f()) << endl;
519  cout << " last sample: "
520  << data(data.l()) << endl;
521  if (dumpsamples)
522  {
523  cout << "BEGIN OF DUMP: data values" << endl;
524  for (int i=data.f(); i<=data.l(); ++i)
525  {
526  cout << data(i) << endl;
527  }
528  cout << "END OF DUMP: data values" << endl;
529  }
530  }
531  {
532  cout << endl;
533  libtime::TRelativeTime dt
534  =libtime::double2time(record.dt());
535  libtime::TRelativeTime length=dt*(record.nsamples()-1);
536  libtime::TAbsoluteTime date=record.date();
537  libtime::TAbsoluteTime next=(date+dt+length);
538  cout << " sampling interval: "
539  << dt.timestring() << endl;
540  cout << " length of record: "
541  << length.timestring() << endl;
542  cout << " start of this record: "
543  << date.timestring() << endl;
544  cout << " expected start of next record: "
545  << next.timestring() << endl;
546  }
547  }
548  else
549  {
550  cout << "record is invalid!" << endl;
551  }
552  }
553  } // end reader mode
554 
555  /*======================================================================*/
556 
557  if (streammode)
558  {
559  cout << endl;
560  cout << "stream mode" << endl;
561  cout << "===========" << endl;
562  cout << "format modifiers: " << modifiers << endl;
563  if (silent)
564  {
565  cout << "silent mode: only imseedstream produces output" << endl;
566  }
567 
568  std::ifstream ifs(filename.c_str());
569  datrw::imseedstream is(ifs, modifiers, verbosemode);
570 
571  int itrace=0;
572  while (ifs.good() && is.good() && (!is.last()))
573  {
574  datrw::Tiseries series;
575  if (skipmode) { is.skipseries(); }
576  else { is >> series; }
577  ++itrace;
578  if (!silent)
579  {
580  cout << endl;
581  cout << "TRACE #" << itrace << endl;
582  cout << "=========" << endl;
583  }
584  if (is.last() && (!silent))
585  { cout << "(is the last trace in the file)" << endl; }
586 
587  sff::WID2 wid2line;
588  is >> wid2line;
589  if (!silent) { cout << wid2line.line() << endl; }
590 
591  if (!silent)
592  {
593  if (skipmode)
594  {
595  cout << "data samples were skipped" << endl;
596  }
597  else
598  {
599  cout << "series contains " << series.size()
600  << " samples" << endl;
601  cout << "first (" << series.f() << ") sample: "
602  << series(series.f()) << endl;
603  cout << "last (" << series.l() << ") sample: "
604  << series(series.l()) << endl;
605  }
606 
607  if (is.hasinfo())
608  {
609  sff::INFO infoline;
610  is >> infoline;
611  cout << infoline.line() << endl;;
612  }
613 
614  if (is.hasfree())
615  {
616  sff::FREE freeblock;
617  is >> freeblock;
618  cout << freeblock;
619  }
620  }
621  }
622  } // end stream mode
623  }
624 }
#define DATRW_assert(C, M)
Check an assertion and report by throwing an exception.
Definition: error.h:92
static const int blocksize
size of frame in bytes
Definition: seedstructs.h:465
Steim (1) compression.
Definition: seedstructs.h:102
Ecpu_type cpu()
check for my CPU model
Definition: bytesex.cc:73
const char *const nframes
keywords for consistency checks
libtime::TRelativeTime dt()
return sampling interval of HPMO data acquisition (i.e. 5 sec)
Definition: readhpmo.cc:83
Ecpu_type
Define different CPU type that are recognized.
Definition: bytesex.h:88
class to read mini-SEED data
Definition: mseed.h:163
const char *const data
keywords for consistency checks
bool needswap(const unsigned char &bytesex)
check bytesex
Definition: mseedread.cc:192
aff::Series< Tvalue > Tseries
type of container for sample data
Definition: mseedread.h:159
unknown CPU
Definition: bytesex.h:94
Steim (2) compression.
Definition: seedstructs.h:103
#define MSEEDTEST_VERSION
Definition: mseedtest.cc:41
bool inconsistencies_are_not_fatal
make inconsistencies non fatal
Definition: mseedread.h:134
void dump(const ControlHeader &s, std::ostream &os)
aff::Series< int > Tiseries
Definition: types.h:47
unsigned char format
Encoding Format.
Definition: seedstructs.h:355
static const int standard_block_size
standard block size for mini-SEED files (in SeisComP)
Definition: mseedread.h:84
Intel CPU.
Definition: bytesex.h:90
unsigned char bytesex
Word order.
Definition: seedstructs.h:356
Here is the call graph for this function: