GPLIB++
MtuFormat.cpp
Go to the documentation of this file.
1 #include "MtuFormat.h"
2 #include "FatalException.h"
3 #include <iostream>
4 #include <algorithm>
5 #include <boost/date_time/gregorian/gregorian_types.hpp>
6 #include <boost/date_time/posix_time/posix_time.hpp>
7 #include <boost/cast.hpp>
8 #include <time.h>
9 
10 using namespace std;
11 namespace gplib
12  {
13  const char tagsize = 32;
14 
15  MtuFormat::MtuFormat()
16  {
17  }
18 
19  MtuFormat::~MtuFormat()
20  {
21  }
22 
23  void MtuFormat::ReadValue(TimeSeriesComponent &CurrChannel, char *pos)
24  {
25  unsigned char byte1, byte2, byte3;
26  int datavalue;
27 
28  byte1 = *pos;
29  byte2 = *(pos + 1);
30  byte3 = *(pos + 2);
31  datavalue = ByteToInt(byte1, byte2, byte3);
32  CurrChannel.GetData().push_back(datavalue);
33  }
34 
35  int MtuFormat::ByteToInt(unsigned char first, unsigned char second,
36  unsigned char last)
37  {
38  const char highbit = 0x80;
39  int value;
40  if (last & highbit)
41  {
42  last = ~last;
43  second = ~second;
44  first = ~first;
45  value = -(last * 65536 + second * 256 + first + 1);
46  }
47  else
48  value = last * 65536 + second * 256 + first;
49  return (value);
50  }
51 
52  void MtuFormat::ReadRecord(ifstream &infile)
53  {
54  unsigned char CurrentTag[tagsize];
55  int recordlength;
56 
57  char *buffer;
58  char *currentbyte;
59 
60  infile.read((char *) CurrentTag, tagsize);
61  if (infile.good())
62  {
63  startsec = CurrentTag[0];
64  startmin = CurrentTag[1];
65  starthr = CurrentTag[2];
66  startday = CurrentTag[3];
67  startmonth = CurrentTag[4];
68  startyear = CurrentTag[5];
69  startdow = CurrentTag[6];
70  startcentury = CurrentTag[7];
71  serialnumber = CurrentTag[9] * 256 + CurrentTag[8];
72  nscans = CurrentTag[11] * 256 + CurrentTag[10];
73  nchannels = CurrentTag[12];
74  taglength = CurrentTag[13];
75  status = CurrentTag[14];
76  saturationflags = CurrentTag[15];
77  futurereserved = CurrentTag[16];
78  samplelength = CurrentTag[17];
79  sampledenom = boost::numeric_cast<double>(CurrentTag[19] * 256
80  + CurrentTag[18]);
81  sampleunit = CurrentTag[20];
82  clockstatus = CurrentTag[21];
83  clockerror = 16777216 * CurrentTag[25] + 65536 * CurrentTag[24]
84  + 256 * CurrentTag[23] + CurrentTag[22];
85  for (int i = 0; i < 6; ++i)
86  reserved[i] = CurrentTag[i + 26];
87  switch (sampleunit)
88  {
89  case 0:
90  sampleenum = 1.0;
91  break;
92  case 1:
93  sampleenum = 60.0;
94  break;
95  case '2':
96  sampleenum = 3600.0;
97  break;
98  case '3':
99  sampleenum = 3600.0 * 24.0;
100  break;
101  }
102  const double samplerate = sampledenom / sampleenum;
103  Hx.SetSamplerate(samplerate);
104  Hy.SetSamplerate(samplerate);
105  Hz.SetSamplerate(samplerate);
106  Ex.SetSamplerate(samplerate);
107  Ey.SetSamplerate(samplerate);
108  recordlength = nscans * nchannels;
109 
110  TimeSeries::ttime basetime(boost::gregorian::date(startcentury
111  * 100 + startyear, startmonth, startday),
112  boost::posix_time::time_duration(starthr, startmin, startsec));
113 
114  buffer = new char[recordlength * samplelength];
115  infile.read(buffer, recordlength * samplelength);
116  currentbyte = buffer;
117  for (int i = 0; i < nscans; ++i)
118  {
119  t.push_back(basetime + boost::posix_time::microseconds(
120  boost::numeric_cast<unsigned int>(i * 1000000.0
121  / samplerate)));
122  ReadValue(Ex, currentbyte);
123  currentbyte += samplelength;
124  ReadValue(Ey, currentbyte);
125  currentbyte += samplelength;
126  ReadValue(Hx, currentbyte);
127  currentbyte += samplelength;
128  ReadValue(Hy, currentbyte);
129  currentbyte += samplelength;
130  ReadValue(Hz, currentbyte);
131  currentbyte += samplelength;
132  }
133  delete[] buffer;
134  }
135  }
136 
137  void MtuFormat::GetData(const std::string filename)
138  {
139  ifstream infile(filename.c_str(), ios::binary);
140  if (infile)
141  {
142  while (infile.good())
143  {
144  ReadRecord(infile);
145  }
146  }
147  else
148  {
149  throw FatalException("Infile does not exist: " + filename);
150  }
151  }
152 
153  void MtuFormat::GetData()
154  {
155 
156  }
157 
158  void MtuFormat::MakeGood()
159  {
160  status = 0;
161  saturationflags = 0;
162  }
163 
164  void MtuFormat::WriteNum(double number, ofstream &outfile)
165  {
166  unsigned char high;
167  unsigned char middle;
168  unsigned char low;
169  char buffer[3];
170  unsigned int intnumber;
171  if (number >= 0)
172  intnumber = int(abs(floor(number)));
173  else
174  intnumber = ~int(abs(floor(number))) + 1;
175  high = intnumber / 65536;
176  middle = (intnumber % 65536) / 256;
177  low = intnumber % 256;
178 
179  buffer[0] = low;
180  buffer[1] = middle;
181  buffer[2] = high;
182  outfile.write(buffer, 3);
183  }
184 
185  void MtuFormat::UpDateHeader(unsigned char *&header, const int firstscan)
186  {
187  tm currtime = boost::posix_time::to_tm(t.at(firstscan)); //convert boost time to old c-style struct
188  header[0] = boost::numeric_cast<char>(currtime.tm_sec); // read out seconds part
189  header[1] = boost::numeric_cast<char>(currtime.tm_min); //boost::numeric_cast takes care of type conversion
190  header[2] = boost::numeric_cast<char>(currtime.tm_hour);
191  boost::gregorian::greg_year_month_day currdate =
192  t.at(firstscan).date().year_month_day(); //convert date
193  header[3] = boost::numeric_cast<char>(currdate.day.as_number());
194  header[4] = boost::numeric_cast<char>(currdate.month.as_number());
195  header[5] = boost::numeric_cast<char>(currdate.year % 100);
196  header[6] = boost::numeric_cast<char>(currtime.tm_wday); // this is the day of week (between 0 and 6)
197  header[7] = boost::numeric_cast<char>(currdate.year / 100);
198  }
199 
200  void MtuFormat::WriteData(const std::string filename)
201  {
202 
203  int nrecords = 0;
204  int firstscan = 0;
205  unsigned char *header = new unsigned char[tagsize];
206 
207  header[8] = serialnumber % 256;
208  header[9] = serialnumber / 256;
209  header[10] = nscans % 256;
210  header[11] = nscans / 256;
211  header[12] = nchannels;
212  header[13] = taglength;
213  header[14] = status;
214  header[15] = saturationflags;
215  header[16] = futurereserved;
216  header[17] = samplelength;
217  header[18] = boost::numeric_cast<unsigned int>(sampledenom) % 256;
218  header[19] = boost::numeric_cast<unsigned int>(sampledenom) / 256;
219  header[20] = sampleunit;
220  header[21] = clockstatus;
221  header[22] = clockerror % 256;
222  header[23] = (clockerror % 65536) / 256;
223  header[24] = (clockerror % 16777216) / 65536;
224  header[25] = clockerror / 16777216;
225  for (int i = 0; i < 6; ++i)
226  header[i + 26] = reserved[i];
227  nrecords = Size() / nscans;
228 
229  ofstream outfile(filename.c_str());
230  for (int i = 0; i < nrecords; ++i)
231  {
232  UpDateHeader(header, firstscan);
233  outfile.write((char *) header, tagsize);
234  for (int j = 0; j < nscans; ++j)
235  {
236 
237  WriteNum(Ex.GetData().at(firstscan + j), outfile);
238  WriteNum(Ey.GetData().at(firstscan + j), outfile);
239  WriteNum(Hx.GetData().at(firstscan + j), outfile);
240  WriteNum(Hy.GetData().at(firstscan + j), outfile);
241  WriteNum(Hz.GetData().at(firstscan + j), outfile);
242  }
243  firstscan += nscans;
244 
245  }
246  }
247 
248  MtuFormat& MtuFormat::operator=(MtuFormat &source)
249  {
250  if (this != &source)
251  {
252  this->TimeSeries::operator=(source);
253  }
254  return *this;
255  }
256 
257  MtuFormat& MtuFormat::operator=(TimeSeries &source)
258  {
259  this->TimeSeries::operator=(source);
260  return *this;
261  }
262  }
const char tagsize
Definition: MtuFormat.cpp:13
std::vector< double > & GetData()
Access for data vector, for ease of use and efficiency we return a reference.
This class is the base class for all classes dealing with MT time series.
Definition: TimeSeries.h:14
TimeSeriesComponent is the base storage class for all types of time series data.
Read and write phoenix mtu binary files.
Definition: MtuFormat.h:13
The basic exception class for all errors that arise in gplib.