DATRW++ library: seismic data I/O with multiple formats
imseedstream.cc
Go to the documentation of this file.
1 /*! \file imseedstream.cc
2  * \brief provide mini-SEED data (implementation)
3  *
4  * ----------------------------------------------------------------------------
5  *
6  * \author Thomas Forbriger
7  * \date 15/07/2004
8  *
9  * provide mini-SEED data (implementation)
10  *
11  * ----
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25  * ----
26  *
27  * Copyright (c) 2004 by Thomas Forbriger (BFO Schiltach)
28  *
29  * REVISIONS and CHANGES
30  * - 15/07/2004 V1.0 Thomas Forbriger (thof)
31  * - 24/07/2006 V1.1 reading function was not comparing record start
32  * time against expected record start time
33  * - 29/06/2007 V1.2 prefer to use our own functions
34  * - 23/11/2010 V1.3 introduced static members
35  * - 13/09/2011 V1.4 support format modifiers for ASCII dump
36  * - 08/05/2014 V1.5 add format modifier to tolerate time jitter
37  * - 22/07/2014 V1.6 thof: support new format modifier: estimateNframes
38  * - 05/07/2016 V1.7 thof: evaluate format modifiers to adjust
39  * consistency checks
40  * - 12/07/2016 V1.8 thof: provide usec consistency check
41  * - 18/11/2016 V1.9 use debug flag in base class
42  *
43  * ============================================================================
44  */
45 #define DATRW_IMSEEDSTREAM_CC_VERSION \
46  "DATRW_IMSEEDSTREAM_CC V1.9"
47 
48 #include <datrwxx/util.h>
49 #include <datrwxx/mseed.h>
50 #include <datrwxx/mseedread.h>
51 #include <aff/subarray.h>
52 #include <datrwxx/debug.h>
53 #include <vector>
54 #include <string>
55 #include <datrwxx/formatmodifier.h>
56 #include <datrwxx/mseed_keywords.h>
57 
58 namespace datrw {
59 
60  const std::ios_base::openmode
61  imseedstream::openmode=std::ios_base::in|std::ios_base::binary;
62 
63  //@{
64  /*! \brief Format properties
65  * \ingroup group_mseed
66  */
67  const bool mseed::isbinary=true;
68  const char* const mseed::streamID="mseed";
69  //@}
70 
71  /*======================================================================*/
72 
73  /*! \class imseedstream
74  *
75  * \ingroup group_mseed
76  * \paragraph mseed_imseedstream_internals Internals of imseedtream
77  *
78  * We must always be one record in advance. Data reading will be done by
79  * concatenating several MiniSEED records. A time series will be
80  * terminated after reading a noncontiguous MiniSEED record. We have to
81  * store this record after reading and thus must always be one record
82  * ahead.
83  *
84  * Data read ahead is stored in imseedstream::Mrecord which is of type
85  * mseed::Record.
86  */
87 
88  /*----------------------------------------------------------------------*/
89 
90  imseedstream::imseedstream(std::istream& is,
91  const std::string& modifier,
92  const bool& debug):
93  Tbase(is, true, true, true, debug), Mmodifier(modifier),
94  Mdumpascii(false), Mchecks(true, true)
95  {
96  datrw::Subformat subformat(Mmodifier);
98  subformat(mseed::key::ttolerance, "0.") >> this->Mttolerance;
100 
101  // note: flags have opposite meaning compared to subformat flags
102  if (subformat.isset(mseed::key::nonfatal))
103  {
104  std::string checks=subformat.value(mseed::key::nonfatal);
105  bool all=(checks.find(mseed::key::all)!=std::string::npos);
107  =!(all||(checks.find(mseed::key::nframes)!=std::string::npos));
109  =!(all||(checks.find(mseed::key::nsamples)!=std::string::npos));
111  =!(all||(checks.find(mseed::key::data)!=std::string::npos));
113  =!(all||(checks.find(mseed::key::usec)!=std::string::npos));
114  }
115 
116  // note: flags have opposite meaning compared to subformat flags
117  if (subformat.isset(mseed::key::skipcheck))
118  {
119  std::string checks=subformat.value(mseed::key::skipcheck);
120  bool all=(checks.find(mseed::key::all)!=std::string::npos);
122  =!(all||(checks.find(mseed::key::nframes)!=std::string::npos));
124  =!(all||(checks.find(mseed::key::nsamples)!=std::string::npos));
126  =!(all||(checks.find(mseed::key::data)!=std::string::npos));
128  =!(all||(checks.find(mseed::key::usec)!=std::string::npos));
129  }
130 
132  "imseedstream::imseedstream()");
133 
134  /* We must always be one record in advance. Data reading will be done by
135  * concatenating several MiniSEED records. A time series will be
136  * terminated after reading a noncontiguous MiniSEED record. We have to
137  * store this record after reading and thus must always be one record
138  * ahead.
139  */
141  DATRW_debug(Mdebug, "Mrecord read", Mrecord.wid2.line());
142  } // imseedstream::imseedstream(std::istream& is, const bool& debug)
143 
144  /*----------------------------------------------------------------------*/
145 
147  {
148  return(datrw::util::convert<Tiseries,Tfseries>(this->read()));
149  } // Tfseries imseedstream::fseries()
150 
151  /*----------------------------------------------------------------------*/
152 
154  {
155  return(datrw::util::convert<Tiseries,Tdseries>(this->read()));
156  } // Tdseries imseedstream::dseries()
157 
158  /*----------------------------------------------------------------------*/
159 
161  {
162  return(this->read());
163  } // Tiseries imseedstream::dseries()
164 
165  /*----------------------------------------------------------------------*/
166 
168  {
169  this->read(true);
170  } // void imseedstream::skipseries()
171 
172  /*----------------------------------------------------------------------*/
173 
174  /*! \brief read next trace from file.
175  *
176  * All reading is controlled within this function...
177  *
178  * File reading always is one record ahead.
179  * The record being read in advance is stored in member field
180  * imseedstream::Mrecord.
181  * This type of operation is necessary, since data data contiguity can only
182  * be checked after the next record has been read.
183  * If this record is not contiguous, it must be stored for the next read
184  * request, where it will provide the first samples of the next trace.
185  *
186  * Reading is done as follows:
187  * -# Data records are read from input as long as the next record read is
188  * contiguous to the previous one.
189  * They are intermediately stored in a vector.
190  * -# After having read all contiguous records, the total number of samples
191  * in the trace is established and data samples can be collected in a
192  * series container.
193  */
194  Tiseries imseedstream::read(const bool& skipdata)
195  {
196  DATRW_debug(Mdebug, "imseedstream::read", "entered reading function");
197 
198  // define vector of records, where input data are collected
199  typedef std::vector<Tiseries> Tvecofrecorddata;
200  Tvecofrecorddata vecofrecorddata;
201 
202  // abort is last record recently read from file is not valid
203  // this indicates that the last reading operation arrived at the end of
204  // file
206  "invalid record; passed end of file?");
207 
208  /* The record present in this->Mrecord form the beginning of the next
209  * trace. Its WID2 header defines the trace to be read. Only records
210  * matching this header may be added to the current trace. The this as a
211  * base.
212  */
213  sff::WID2 wid2line=Mrecord.wid2;
214  libtime::TRelativeTime dt=libtime::double2time(wid2line.dt);
215 
216  /* Define a WID2 comparison instance to check whether WID headers of
217  * subsequent record match the header of the total trace being assembled.
218  */
219  sff::WID2compare wid2areequal(sff::Fdate
220  | sff::Fstation
221  | sff::Fchannel
222  | sff::Fauxid
223  | sff::Fdt
224  | sff::Fcalib
225  | sff::Fcalper
226  | sff::Finstype
227  | sff::Fhang
228  | sff::Fvang);
229  // set date tolerance
230  wid2areequal.setdatetolerance(this->Mttolerance*1.e-6/wid2line.dt);
231 
232  /* collect data
233  * ------------
234  * Read record sequentially from file and check whether the recently read
235  * record is part of the trace. Count the number of samples while doing
236  * this.
237  */
238  DATRW_debug(Mdebug, "imseedstream::read", "collect data");
239 
240  sff::WID2 nextwid2=wid2line;
241 
242  int nsamples=0;
243  bool contiguous=true;
244 
245  while(Mrecord.valid && Mis.good() && contiguous)
246  {
247  DATRW_debug(Mdebug, "imseedstream::read",
248  "save data from record ("
249  << Mrecord.data.size() << " samples)");
250 
252  if (!skipdata) { vecofrecorddata.push_back(data.copyout()); }
253 
254  DATRW_debug(Mdebug, "imseedstream::read", "last data index " <<
255  data.last());
256 
257  /*
258  * Remember value of last sample in previous record to be compared to
259  * retrospect value derived from the succeeding record. A mismatch will
260  * indicate non-contiguous data.
261  */
262  int xm1=data(data.last());
263  nsamples += Mrecord.wid2.nsamples;
264  nextwid2.date=wid2line.date+dt*nsamples;
265 
266  DATRW_debug(Mdebug, "imseedstream::read", "read next");
267 
269 
270  DATRW_debug(Mdebug, "imseedstream::read", "compare next");
271  DATRW_debug(Mdebug, "imseedstream::read", "expected wid2: " <<
272  nextwid2.line());
273  DATRW_debug(Mdebug, "imseedstream::read", " this wid2: " <<
274  Mrecord.wid2.line());
275 
276  if (Mrecord.valid)
277  {
278  if (! (wid2areequal(Mrecord.wid2, nextwid2) && (xm1 == Mrecord.xm1)))
279  {
280  contiguous=false;
281  DATRW_debug(Mdebug, "imseedstream::read", "non-contiguous data");
282  }
283  else
284  {
285  DATRW_debug(Mdebug, "imseedstream::read", "data is still contiguous");
286  }
287  }
288  else
289  {
290  // reading has met the end of file
291  contiguous=false;
292  this->setlast();
293  }
294  }
295  wid2line.nsamples=nsamples;
296 
297  // extract data samples
298  DATRW_debug(Mdebug, "imseedstream::read", "extract data");
299  Tiseries series;
300  if (!skipdata)
301  {
302  DATRW_debug(Mdebug, "imseedstream::read", "do not skip");
303  Tvecofrecorddata::const_iterator I(vecofrecorddata.begin());
304  DATRW_debug(Mdebug, "imseedstream::read", "create buffer");
305  series=Tiseries(0,nsamples-1);
306  nsamples=0;
307  DATRW_debug(Mdebug, "imseedstream::read", "cycle vector");
308  while (I != vecofrecorddata.end())
309  {
310  DATRW_debug(Mdebug, "imseedstream::read", "create dest");
311  Tiseries dest=aff::subarray(series)(nsamples,nsamples+I->size()-1);
312  DATRW_debug(Mdebug, "imseedstream::read", "copy to dest");
313  dest.copyin(*I);
314  DATRW_debug(Mdebug, "imseedstream::read", "step nsamples");
315  nsamples += I->size();
316  ++I;
317  }
318  }
319 
320  // set headers
321  this->setwid2(wid2line);
322  return (series);
323  } // Tiseries imseedstream::read(const bool& skipdata)
324 
325 } // namespace datrw
326 
327 /* ----- END OF imseedstream.cc ----- */
virtual Tdseries dseries()
bool Mdumpascii
dump ASCII data if true
Definition: mseed.h:182
bool fatal
Consequences of check.
Definition: mseed.h:77
const char *const usec
keywords for consistency checks
#define DATRW_assert(C, M)
Check an assertion and report by throwing an exception.
Definition: error.h:92
ConsistencyCheckControl nsamples
Check for consistent number of samples.
Definition: mseed.h:106
ConsistencyCheckControl data
Check for consistent data values.
Definition: mseed.h:121
provide format modifiers (prototypes)
datrw::mseed::Record Mrecord
data read ahead
Definition: mseed.h:180
macro function for debugging output (prototypes)
aff::Series< float > Tfseries
Definition: types.h:46
static const std::ios_base::openmode openmode
Definition: mseed.h:175
datrw::mseed::ConsistencyChecks Mchecks
Definition: mseed.h:186
const char *const nframes
keywords for consistency checks
virtual Tiseries iseries()
libtime::TRelativeTime dt()
return sampling interval of HPMO data acquisition (i.e. 5 sec)
Definition: readhpmo.cc:83
void read(std::istream &is, const bool &dumpascii=false, const bool &estimateNframes=false, const ConsistencyChecks &checks=ConsistencyChecks(true, true))
read and decode a record to SFF
imseedstream(std::istream &is, const std::string &modifier="", const bool &debug=false)
Definition: imseedstream.cc:90
const char *const ttolerance
keywords for format modifiers
aff::Series< double > Tdseries
Definition: types.h:45
virtual void skipseries()
const int nsamples
number of samples per minute block and channel
Definition: hpmodata.h:51
ConsistencyCheckControl usec
Check for usec field being in specified range.
Definition: mseed.h:134
std::istream & Mis
Definition: datread.h:126
void setwid2(const sff::WID2 &wid2)
Definition: datread.cc:113
Tiseries read(const bool &skipdata=false)
read file
#define DATRW_assert_modifiers_are_recognized(S, F)
abort if user passed unused modifiers
const char *const data
keywords for consistency checks
Tiseries data
Definition: mseed.h:146
const char *const dumpascii
keywords for format modifiers
::sff::WID2 wid2
Definition: mseed.h:144
Root namespace of library.
Definition: aalibdatrwxx.cc:16
bool MestimateNframes
estimate frame count flags controlling consistency checks
Definition: mseed.h:184
utilities used by more than one type of data reader (prototypes)
bool docheck
Activation of check.
Definition: mseed.h:72
const char *const skipcheck
keywords for format modifiers
double Mttolerance
timing tolerance in microseconds
Definition: mseed.h:183
aff::Series< int > Tiseries
Definition: types.h:47
#define DATRW_debug(C, N, M)
produce debug output
Definition: debug.h:50
Class to handle format modifiersThis class is used to parse a format modifier string. Detailed instructions will be given upon request. For some hints have a look at tests/libdatrwxxtests.c.
const char *const all
keywords for consistency checks
const char *const streamID
Format properties.
Definition: imseedstream.cc:68
bool isset(const std::string &k) const
check if user provided this key
provide mini-SEED data (prototypes)
std::string Mmodifier
format modifier
Definition: mseed.h:181
const char *const nsamples
number of samples per minute block and channel
std::string value(const std::string &k, const std::string &dev="false") const
function operator returns string
const char *const estimateNframes
keywords for format modifiers
ConsistencyCheckControl nframes
Check for consistent number of frames.
Definition: mseed.h:98
const bool isbinary
Format properties.
Definition: imseedstream.cc:67
virtual Tfseries fseries()
const char *const nonfatal
keywords for format modifiers