DATRW++ library: seismic data I/O with multiple formats
tsoftdata.cc
Go to the documentation of this file.
1 /*! \file tsoftdata.cc
2  * \brief class to store TSOFT data (implementation)
3  * \ingroup group_tsoft
4  *
5  * ----------------------------------------------------------------------------
6  *
7  * \author Thomas Forbriger
8  * \date 16/09/2009
9  *
10  * class to store TSOFT data (implementation)
11  *
12  * Copyright (c) 2009 by Thomas Forbriger (BFO Schiltach)
13  *
14  * ----
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28  * ----
29  *
30  * REVISIONS and CHANGES
31  * - 16/09/2009 V1.0 Thomas Forbriger
32  * - 02/12/2011 V1.1 prepared for input stream modifiers
33  * - 08/07/2016 V1.2 make correct use of new DATRW_report_assert
34  *
35  * ============================================================================
36  */
37 #define DATRW_TSOFTDATA_CC_VERSION \
38  "DATRW_TSOFTDATA_CC V1.2"
39 
40 #include <datrwxx/error.h>
41 #include <datrwxx/tsoftdata.h>
42 #include <sstream>
43 
44 namespace datrw {
45 
46  namespace tsoft {
47 
48  /*======================================================================*/
49  // string constants
50 
51  const char* tagbegin="[";
52  const char* tagend="]";
53 
54  const char* tagdata="DATA";
55  const char* tagchannels="CHANNELS";
56  const char* tagunits="UNITS";
57  const char* tagfileid="TSF-file";
58  const char* tagtimeformat="TIMEFORMAT";
59  const char* tagincrement="INCREMENT";
60  const char* tagundetval="UNDETVAL";
61 
62  const char* NSP="NSP";
63 
64  /*======================================================================*/
65  // class Line
66 
67  //! read one line from data file
68  Line::Line(const std::string& line):
69  Mline(line), Mhastag(false), Mhascontent(false)
70  {
71  //! check existence of tag
72  if (Mline.substr(0,1) == tagbegin)
73  {
74  Mhastag=true;
75  // length without trailing \0
76  const string::size_type len=line.length();
77  // find end of tag
78  string::size_type i=1;
79  string::size_type j=line.find_first_of(tagend, i);
80  Mtag=line.substr(i,j-i);
81  j++;
82  if (j<len)
83  {
84  i=j;
85  j=line.find_first_not_of (" ", i);
86  if (j <len)
87  {
88  Mhascontent=true;
89  Mcontent=line.substr(j,len-j+1);
91  }
92  }
93  }
94  } // Line::Line(const std::string& line)
95 
96  /*======================================================================*/
97  // class Channelinfo
98 
99  //! constructor for Channelinfo
101  Mlocation(NSP), Minstrument(NSP), Mdatatype(NSP), Munits(NSP)
102  {
103  } // Channelinfo::Channelinfo()
104 
105  /*----------------------------------------------------------------------*/
106 
107  //! extract channel info from TSOFT line
108  void Channelinfo::setchannelinfo(const std::string& line)
109  {
110  Tvos vos=stringtovec(line);
111  Tvos::const_iterator I=vos.begin();
112  if (I != vos.end()) { Mlocation = *I; ++I; }
113  if (I != vos.end()) { Minstrument = *I; ++I; }
114  if (I != vos.end()) { Mdatatype = *I; ++I; }
115  // std::cout << "+++" << Mdatatype << "+++" << std::endl;
116  } // Channelinfo::setchannelinfo(const std::string& line)
117 
118  /*======================================================================*/
119  // class Dataline
120 
121  //! read one line of samples from data file
122  Dataline::Dataline(const std::string& line):
123  Mline(line)
124  {
125  int year,month,day,hour,minute ,second;
126  std::istringstream iss(Mline);
127  iss >> year >> month >> day >> hour >> minute >> second;
128  DATRW_report_assert(iss.good(),
129  "read beyond end of data line when reading date and time" << line);
130  DATRW_assert(iss.good(), "empty data line or read beyond end of file");
131  Mtime=libtime::TAbsoluteTime(year,month,day,hour,minute,second);
132  double sample;
133  while (iss.good())
134  {
135  iss >> sample;
136  //if (iss.good()) { Msamples.push_back(sample); }
137  Msamples.push_back(sample);
138  // std::cout << "sample " << sample << std::endl;
139  }
140  } // Dataline::Dataline(const std::string& line)
141 
142  /*----------------------------------------------------------------------*/
143 
144  //! return one sample and check index
145  double Dataline::sample(const int& i) const
146  {
147  DATRW_assert(((i>=0)&&(i<this->nsamples())),
148  "index out of range");
149  return(Msamples[i]);
150  } // std::string Dataline::sample(const int& i) const
151 
152 
153  /*======================================================================*/
154  // class Datasequence
155 
157  {
158  this->initialize();
159  } // Datasequence::Datasequence()
160 
161  /*----------------------------------------------------------------------*/
162 
163  //! return time of next sample after last samples
164  libtime::TAbsoluteTime Datasequence::timeofnextsample(const bool&
165  debug) const
166  {
167  if (debug)
168  {
169  std::cout << " date: " << this->date().timestring() << std::endl;
170  std::cout << " interval: " << this->interval().timestring() << std::endl;
171  std::cout << " nsamples: " << this->nsamples() << std::endl;
172  }
173  libtime::TAbsoluteTime retval=this->date();
174  retval += (this->nsamples()*this->interval());
175  return(retval);
176  } // libtime::TAbsoluteTime Datasequence::timeofnextsample() const
177 
178  /*----------------------------------------------------------------------*/
179 
181  {
182  Msamples.reserve(86500);
183  Msamples.clear();
184  Mdate=libtime::TAbsoluteTime();
185  Minterval=libtime::double2time(0);
186  } // void Datasequence::initialize()
187 
188  /*----------------------------------------------------------------------*/
189 
191  {
192  Tdseries series(Msamples.size());
193  Tvod::const_iterator I=Msamples.begin();
194  for (aff::Tsubscript i=series.f();
195  ((i<=series.l()) && (I!=Msamples.end()));
196  ++i, ++I)
197  {
198  series(i)= (*I);
199  }
200  return(series);
201  } // Tdseries Datasequence::series() const
202 
203  /*======================================================================*/
204  // class Channeldata
205 
207  {
209  } // Channeldata::Channeldata()
210 
211  /*----------------------------------------------------------------------*/
212 
214  {
215  if (Mcollector.nsamples()>0)
216  {
221  Mtraces.push_back(trace);
223  }
224  } // Channeldata::flushcollector()
225 
226  /*----------------------------------------------------------------------*/
227 
228  void Channeldata::push_sample(const libtime::TAbsoluteTime& intime,
229  const double& invalue,
230  const double& undetval,
231  const libtime::TRelativeTime& dt,
232  const ReaderConfig& rc,
233  const bool& debug)
234  {
235  // copy value to allow modification
236  double value=invalue;
237  libtime::TAbsoluteTime time=intime;
238  // replace flag value if requested
239  if ((value == undetval) && (rc.setundetval))
240  {
241  value=rc.flagvalue;
242  }
243  // handle value if valid or if UNDETVAL values are requested to be read
244  if ((value != undetval) || (rc.keepundetval))
245  {
246  if (debug)
247  {
248  std::cout << " yes, take this sample" << std::endl;
249  }
250  // check, whether collector is already in use
251  bool insequence = (Mcollector.nsamples() > 0);
252  // bridge sample if requested
253  if (rc.bridgesamples)
254  {
255  if (time == rc.bridgetime)
256  {
257  if (insequence)
258  {
259  time = Mcollector.timeofnextsample();
260  if (rc.flagbridged)
261  {
262  value=rc.bridgeflagvalue;
263  }
264  }
265  else
266  {
267  DATRW_report_assert(insequence,
268  "WARNING (Channeldata::push_sample): TSOFT reading\n"
269  "User requested to bridge data entries labelled with time: "
270  << rc.bridgetime.timestring() << "\n"
271  << "This time label is present in the first entry of the"
272  << "input data.\n"
273  << "First input lines cannot be bridged.");
274  }
275  }
276  }
277  // if collector is in use, then check is current value matches
278  if (insequence)
279  {
280  insequence = ((time == Mcollector.timeofnextsample(debug))
281  && (dt == Mcollector.interval()));
282  }
283  // if current value does not match: flush collector and start new
284  if (!insequence)
285  {
286  this->flushcollector();
287  Mcollector.date(time);
289  }
290  Mcollector.append(value);
291  }
292  } // void Channeldata::push_sample
293 
294  /*======================================================================*/
295  // class Datacontainer
296 
297  void Datacontainer::push_data(const std::string& line,
298  const double& theundetval,
299  const libtime::TRelativeTime& dt,
300  const bool& debug)
301  {
302  Dataline thedata(line);
303  if (debug)
304  {
305  std::cout << "the line: " << line << std::endl;
306  std::cout << " time: " << thedata.time().timestring() << std::endl;
307  std::cout << " dt: " << dt.timestring() << std::endl;
308  std::cout << " undetval: " << theundetval << std::endl;
309  }
310  // std::cout << "nsamples " << thedata.nsamples() << std::endl;
311  for (int ich=0; ich<thedata.nsamples(); ++ich)
312  {
313  double thesample=thedata.sample(ich);
314  // std::cout << "ich " << ich << " sample " << thesample << std::endl;
315  if (debug)
316  {
317  std::cout << " sample: " << thesample << std::endl;
318  }
319  this->channel(ich).push_sample(thedata.time(),
320  thesample,
321  theundetval,
322  dt, Mreaderconfig,
323  debug);
324  }
325  } // Datacontainer::push_data
326 
327  /*----------------------------------------------------------------------*/
328 
330  {
331  for (unsigned int ich=0; ich<Mchannels.size(); ++ich)
332  {
333  Mchannels[ich].flushcollector();
334  }
335  } // void Datacontainer::flushchannels()
336 
337  /*======================================================================*/
338  // functions
339 
340  //! helper function stringtok
341  Tvos stringtovec(const std::string& line,
342  const std::string& delimiters)
343  {
344  Tvos result;
345  const string::size_type len = line.length();
346  string::size_type i = 0;
347 
348  while ( i < len )
349  {
350  // eat leading whitespace
351  i = line.find_first_not_of (" ", i);
352  if (i == string::npos)
353  return result; // nothing left but white space
354 
355  // find the end of the token
356  string::size_type j = line.find_first_of (delimiters, i);
357 
358  // push token
359  if (j == string::npos) {
360  result.push_back (line.substr(i));
361  return result;
362  } else
363  result.push_back (line.substr(i, j-i));
364 
365  // set up for next loop
366  i = j + 1;
367  }
368  return result;
369  } // Tvos stringtovec(const std::string& line,
370  // const std::string& delimiter=":")
371 
372  /*----------------------------------------------------------------------*/
373 
374  //! helper function trimws
375  void trimws(std::string& line)
376  {
377  // std::cout << "<" << line << ">" << std::endl;
378  if (line.length()>0)
379  {
380  // std::cout << line.length() << " > 0" << std::endl;
381  string::size_type ib=line.find_first_not_of(" ", 0);
382  if (ib==string::npos)
383  {
384  line="";
385  }
386  else
387  {
388  string::size_type il=line.find_last_not_of(" \r", line.length());
389  string::size_type n=il>=ib ? il-ib+1 : 0;
390  if (n==0) { ib = 0; }
391  /*
392  std::cout << "ib = " << ib << "; il = " << il <<
393  "; n = " << n << std::endl;
394  */
395  if ((ib!=0) || (n!=line.length())) { line=line.substr(ib,n); }
396  }
397  }
398  } // trimws(std::string& line)
399 
400  /*----------------------------------------------------------------------*/
401 
402  //! prepare free comment block from channel info
404  {
405  Tlos retval;
406  std::ostringstream oss;
407  oss << "location: " << ci.thelocation();
408  retval.push_back(oss.str());
409  oss.str("");
410  oss << "instrument: " << ci.theinstrument();
411  retval.push_back(oss.str());
412  oss.str("");
413  oss << "datatype: " << ci.thedatatype();
414  retval.push_back(oss.str());
415  oss.str("");
416  oss << "units: " << ci.theunits();
417  retval.push_back(oss.str());
418  return (retval);
419  } // Tvos channelinfofree(const channelinfo& ci)
420 
421  /*----------------------------------------------------------------------*/
422 
423  std::string getDOSline(std::istream& is)
424  {
425  std::string inputline;
426  getline(is, inputline);
427  // check for DOS file
428  // inputline.replace(inputline.find("\r"), 1, "");
429  trimws(inputline);
430  return(inputline);
431  } // std::string getDOSline(std::istream& is)
432 
433  } // namespace tsoft
434 
435 } // namespace datrw
436 
437 /* ----- END OF tsoftdata.cc ----- */
void append(const double &v)
append sample
Definition: tsoftdata.h:275
config parameters for data extractionThese parameters control the way gaps in the input data are hand...
Definition: tsoftconfig.h:57
void push_sample(const libtime::TAbsoluteTime &time, const double &value, const double &undetval, const libtime::TRelativeTime &dt, const ReaderConfig &rc, const bool &debug=false)
push a sample
Definition: tsoftdata.cc:228
libtime::TAbsoluteTime timeofnextsample(const bool &debug=false) const
return time of next sample after last samples
Definition: tsoftdata.cc:164
contains channel info.
Definition: tsoftdata.h:173
ReaderConfig Mreaderconfig
reader configuration
Definition: tsoftdata.h:441
#define DATRW_assert(C, M)
Check an assertion and report by throwing an exception.
Definition: error.h:92
std::list< std::string > Tlos
list of strings.
Definition: tsoftdata.h:108
std::string Mcontent
the content part of the line
Definition: tsoftdata.h:161
Tvod Msamples
vector of data values
Definition: tsoftdata.h:234
Tvocd Mchannels
data sequences
Definition: tsoftdata.h:443
Channeldata()
constructor to initialize
Definition: tsoftdata.cc:206
const char * tagdata
TSOFT data tag.
Definition: tsoftdata.cc:54
std::string Mline
the data line
Definition: tsoftdata.h:230
trace of contiguous data.
Definition: tsoftdata.h:242
const std::string & thedatatype() const
return datatype
Definition: tsoftdata.h:190
libtime::TRelativeTime Minterval
sampling interval
Definition: tsoftdata.h:305
Tvodt Mtraces
data traces
Definition: tsoftdata.h:359
bool Mhascontent
true if this line has a content
Definition: tsoftdata.h:165
libtime::TAbsoluteTime time() const
return time
Definition: tsoftdata.h:221
const std::string & theunits() const
return units
Definition: tsoftdata.h:192
std::vector< std::string > Tvos
vector of strings.
Definition: tsoftdata.h:104
libtime::TRelativeTime dt()
return sampling interval of HPMO data acquisition (i.e. 5 sec)
Definition: readhpmo.cc:83
std::string Minstrument
instrument field in channel name
Definition: tsoftdata.h:197
const char * tagbegin
first character of TSOFT tag
Definition: tsoftdata.cc:51
Line(const std::string &line)
constructor: swallow line
Definition: tsoftdata.cc:68
void series(const Tdseries &s)
set series
Definition: tsoftdata.h:249
double sample(const int &i) const
return specific sample
Definition: tsoftdata.cc:145
Dataline(const std::string &line)
swallow a line
Definition: tsoftdata.cc:122
int nsamples() const
return number of samples in line
Definition: tsoftdata.h:225
const char * tagtimeformat
TSOFT timeformat tag.
Definition: tsoftdata.cc:58
bool Mhastag
true if this line contains a tag
Definition: tsoftdata.h:163
aff::Series< double > Tdseries
Definition: types.h:45
int nsamples() const
return number of samples
Definition: tsoftdata.h:288
const Datatrace & trace(const unsigned int &i) const
return data trace
Definition: tsoftdata.h:332
Tdseries series() const
return samples in a series container
Definition: tsoftdata.cc:190
exception class declaration for libdatrwxx (prototypes)
std::string Mline
the actual line
Definition: tsoftdata.h:157
libtime::TAbsoluteTime Mdate
time of first sample
Definition: tsoftdata.h:303
void trimws(std::string &line)
helper function trimws
Definition: tsoftdata.cc:375
void interval(const libtime::TRelativeTime i)
set sampling interval
Definition: tsoftdata.h:279
libtime::TRelativeTime interval() const
return sampling interval
Definition: tsoftdata.h:294
libtime::TAbsoluteTime date() const
return time of first sample
Definition: tsoftdata.h:290
std::string Mtag
the tag part of the line
Definition: tsoftdata.h:159
const char * tagunits
TSOFT units tag.
Definition: tsoftdata.cc:56
libtime::TAbsoluteTime Mtime
time
Definition: tsoftdata.h:232
const char * tagincrement
TSOFT increment tag.
Definition: tsoftdata.cc:59
const std::string & theinstrument() const
return instrument
Definition: tsoftdata.h:188
Root namespace of library.
Definition: aalibdatrwxx.cc:16
const char * tagend
last character of TSOFT tag
Definition: tsoftdata.cc:52
void initialize()
initialize data sequence
Definition: tsoftdata.cc:180
Channelinfo()
standard constructor
Definition: tsoftdata.cc:100
Tlos channelinfofree(const Channelinfo &ci)
prepare free comment block from channel info
Definition: tsoftdata.cc:403
void setchannelinfo(const std::string &line)
set channel info
Definition: tsoftdata.cc:108
Tvos stringtovec(const std::string &line, const std::string &delimiters)
helper function stringtok
Definition: tsoftdata.cc:341
std::string Mlocation
location field in channel name
Definition: tsoftdata.h:195
const std::string & thelocation() const
return location
Definition: tsoftdata.h:186
const char * NSP
value not specified
Definition: tsoftdata.cc:62
void flushcollector()
function to flush collector to vector of sequences
Definition: tsoftdata.cc:213
void date(const libtime::TAbsoluteTime d)
set time of first sample
Definition: tsoftdata.h:245
Datasequence Mcollector
vector of samples to collect from file
Definition: tsoftdata.h:361
const char * tagfileid
TSOFT fileid tag.
Definition: tsoftdata.cc:57
void push_data(const std::string &line, const double &undetval, const libtime::TRelativeTime &dt, const bool &debug=false)
push a data line
Definition: tsoftdata.cc:297
void flushchannels()
flush all channels
Definition: tsoftdata.cc:329
void date(const libtime::TAbsoluteTime d)
set time of first sample
Definition: tsoftdata.h:277
const char * tagchannels
TSOFT channels tag.
Definition: tsoftdata.cc:55
contains one data line.
Definition: tsoftdata.h:216
std::string Mdatatype
data type field in channel name
Definition: tsoftdata.h:199
Channeldata & channel(const unsigned int &i, const bool &debug=false)
return data for specific channel
Definition: tsoftdata.h:397
libtime::TAbsoluteTime bridgetime
Definition: tsoftconfig.h:82
void interval(const libtime::TRelativeTime i)
set sampling interval
Definition: tsoftdata.h:247
#define DATRW_report_assert(C, M)
Check an assertion and report only.
Definition: error.h:120
std::string getDOSline(std::istream &is)
helper function getDOSline
Definition: tsoftdata.cc:423
const char * tagundetval
TSOFT undetval tag.
Definition: tsoftdata.cc:60