rowdiff.cpp
Go to the documentation of this file.
1 //==============================================================================
2 //
3 // This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
4 //
5 // The GNSSTk is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation; either version 3.0 of the License, or
8 // any later version.
9 //
10 // The GNSSTk is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with GNSSTk; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 // This software was developed by Applied Research Laboratories at the
20 // University of Texas at Austin.
21 // Copyright 2004-2022, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24 
25 //==============================================================================
26 //
27 // This software was developed by Applied Research Laboratories at the
28 // University of Texas at Austin, under contract to an agency or agencies
29 // within the U.S. Department of Defense. The U.S. Government retains all
30 // rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 // Pursuant to DoD Directive 523024
33 //
34 // DISTRIBUTION STATEMENT A: This software has been approved for public
35 // release, distribution is unlimited.
36 //
37 //==============================================================================
38 
97 
99 #include "NewNavInc.h"
100 #include <gnsstk/FileFilterFrameWithHeader.hpp>
101 #include <gnsstk/Rinex3ObsStream.hpp>
102 #include <gnsstk/Rinex3ObsFilterOperators.hpp>
103 #include <gnsstk/TimeString.hpp>
104 
105 #include "DiffFrame.hpp"
106 
107 #include <gnsstk/YDSTime.hpp>
108 
109 using namespace std;
110 using namespace gnsstk;
111 
112 class ROWDiff : public DiffFrame
113 {
114 public:
116  static const int EXIST_ERROR = 2;
118  static const int DIFFS_CODE = 1;
119  ROWDiff(char* arg0)
120  : DiffFrame(arg0, std::string("RINEX Obs")),
121  precisionOption('p',"precision","Limit data comparison to n decimal"
122  " places. Default = 5")
123  {}
124  virtual bool initialize(int argc, char* argv[]) throw();
125 
126 protected:
127  virtual void process();
129 
130 private:
132  static const int DEFAULT_PRECISION = 5;
133 };
134 
135 bool ROWDiff::initialize(int argc, char* argv[]) throw()
136 {
137  if (!DiffFrame::initialize(argc, argv))
138  {
139  return false;
140  }
141  if (precisionOption.getCount())
142  {
143  precision = atoi(precisionOption.getValue()[0].c_str());
144  }
145  else
146  {
147  precision = DEFAULT_PRECISION;
148  }
149  return true;
150 }
151 
153 {
155  ff1(inputFileOption.getValue()[0]), ff2(inputFileOption.getValue()[1]);
156 
157  // no data? FIX make this program faster.. if one file
158  // doesn't exist, there's little point in reading any.
159  if (ff1.emptyHeader())
160  {
161  cerr << "No header information for " << inputFileOption.getValue()[0]
162  << endl;
163  }
164  if (ff2.emptyHeader())
165  {
166  cerr << "No header information for " << inputFileOption.getValue()[1]
167  << endl;
168  }
169  if (ff1.emptyHeader() || ff2.emptyHeader())
170  {
171  cerr << "Check that files exist." << endl;
172  cerr << "diff failed." << endl;
173  exitCode = EXIST_ERROR;
174  return;
175  }
176 
177  // determine whether the two input files have the same observation types
178 
179  Rinex3ObsHeader header1, header2;
180  Rinex3ObsStream ros1(inputFileOption.getValue()[0]),
181  ros2(inputFileOption.getValue()[1]);
182 
183  ros1 >> header1;
184  ros2 >> header2;
185 
186  // find the obs data intersection
187 
188  if (header1.version != header2.version)
189  {
190  cout << "File 1 and file 2 are not the same RINEX version" << endl;
191  // Reading a R2 file in translates/guesses its obsTypes into
192  // R3-style obsIDs, but translating the R3 obsIDs to R2 is
193  // more likely to match. So map R3 -> R2 then change the R2
194  // header to match.
195  if (header1.version < 3 && header2.version >= 3)
196  {
197  header2.prepareVer2Write();
199  for (const auto& r2it : header1.R2ObsTypes)
200  {
201  r3ov.push_back(header2.mapSysR2toR3ObsID["G"][r2it]);
202  }
203  header1.mapObsTypes["G"] = r3ov;
204  ff1.frontHeader().mapObsTypes["G"] = r3ov;
205  }
206  else if (header2.version < 3 && header1.version >= 3)
207  {
208  header1.prepareVer2Write();
210  for (const auto& r2it : header2.R2ObsTypes)
211  {
212  r3ov.push_back(header1.mapSysR2toR3ObsID["G"][r2it]);
213  }
214  header2.mapObsTypes["G"] = r3ov;
215  ff2.frontHeader().mapObsTypes["G"] = r3ov;
216  }
217  }
218 
219  // Find out what obs IDs header 1 has that header 2 does/ doesn't have
220  // add those to intersectionRom/ diffRom respectively.
221  cout << "Comparing the following fields:" << endl;
223  Rinex3ObsHeader::RinexObsMap intersectRom;
224  for (const auto& mit : header1.mapObsTypes)
225  {
226  string sysChar = mit.first;
227  cout << sysChar << ": ";
228  for (const auto& id1 : mit.second)
229  {
230  try
231  {
232  header2.getObsIndex(sysChar, id1);
233  intersectRom[sysChar].push_back(id1);
234  cout << " " << id1.asString();
235  }
236  catch(...)
237  {
238  diffRom[sysChar].push_back(id1);
239  }
240  }
241  cout << endl;
242  }
243 
244  // Find out what obs IDs header 2 has that header 1 doesn't
245  // and add them to diffRom
246  for (const auto& mit : header2.mapObsTypes)
247  {
248  string sysChar = mit.first;
249  for (const auto& id2 : mit.second)
250  {
251  try
252  {
253  header1.getObsIndex(sysChar, id2);
254  }
255  catch(...)
256  {
257  diffRom[sysChar].push_back(id2);
258  }
259  }
260  }
261 
262  // Print out the differences between the obs IDs in header1 and header2
263  if (!diffRom.empty())
264  {
265  cout << "Ignoring unshared obs:" << endl;
266  for (const auto& mit : diffRom)
267  {
268  string sysChar = mit.first;
269  cout << sysChar << ": ";
270  for (const auto& id : mit.second)
271  {
272  cout << id.asString() << " ";
273  }
274  cout << endl;
275  }
276  }
277 
278  std::list<Rinex3ObsData> a =
279  ff1.halfDiff(ff2,Rinex3ObsDataOperatorLessThanFull(intersectRom),
280  precision);
281  std::list<Rinex3ObsData> b =
282  ff2.halfDiff(ff1, Rinex3ObsDataOperatorLessThanFull(intersectRom),
283  precision);
284 
285  pair< list<Rinex3ObsData>, list<Rinex3ObsData> > difflist =
286  pair< list<Rinex3ObsData>, list<Rinex3ObsData> >( a, b);
287 
288  if (difflist.first.empty() && difflist.second.empty())
289  {
290  //Indicate to the user, before exiting, that rowdiff
291  //performed properly and no differences were found.
292  cout << "For the observation types that were compared, "
293  << "no differences were found." << endl;
294  exitCode = 0;
295  return;
296  }
297 
298  // differences found
299  exitCode = DIFFS_CODE;
300 
301  auto firstDiffItr = difflist.first.begin();
302  auto secondDiffItr = difflist.second.begin();
303  while ((firstDiffItr != difflist.first.end()) ||
304  (secondDiffItr != difflist.second.end()))
305  {
306  //Epoch in both files
307  //Epoch only in first file
308  if ((firstDiffItr != difflist.first.end()) &&
309  ((secondDiffItr == difflist.second.end()) ||
310  (firstDiffItr->time < secondDiffItr->time)))
311  {
312  for (const auto& firstObsItr : firstDiffItr->obs)
313  {
314  cout << "<" << setw(3) << (static_cast<YDSTime>(firstDiffItr->time))
315  << ' ' << setw(2) << firstObsItr.first << ' ';
316  string sysString = string(1,firstObsItr.first.systemChar());
317  for (const auto& romIt : intersectRom[sysString])
318  {
319  size_t idx = header1.getObsIndex(sysString, romIt);
320  cout << setw(15) << setprecision(3) << fixed
321  << firstObsItr.second[idx].data << ' ' << romIt.asString()
322  << ' ';
323  }
324  cout << endl;
325  }
326  firstDiffItr++;
327  }
328  //Epoch only in second file
329  else if ((secondDiffItr != difflist.second.end()) &&
330  ((firstDiffItr == difflist.first.end()) ||
331  (secondDiffItr->time < firstDiffItr->time)))
332  {
333  for (const auto& secondObsItr : secondDiffItr->obs)
334  {
335  cout << ">" << setw(3)
336  << (static_cast<YDSTime>(secondDiffItr->time))
337  << ' ' << setw(2) << secondObsItr.first << ' ';
338  string sysString = string(1,secondObsItr.first.systemChar());
339  for (const auto& romIt : intersectRom[sysString])
340  {
341  size_t idx = header2.getObsIndex(sysString, romIt);
342  cout << setw(15) << setprecision(3) << fixed
343  << secondObsItr.second[idx].data << ' '
344  << romIt.asString() << ' ';
345  }
346  cout << endl;
347  }
348  secondDiffItr++;
349  }
350  else if (firstDiffItr->time == secondDiffItr->time)
351  {
352  auto firstObsItr = firstDiffItr->obs.begin();
353  auto secondObsItr = secondDiffItr->obs.begin();
354  // For each satellite
355  while ((firstObsItr != firstDiffItr->obs.end()) ||
356  (secondObsItr != secondDiffItr->obs.end()))
357  {
358  // Both files have data for that satellite
359  if (firstObsItr->first == secondObsItr->first)
360  {
361  string sysString = string(1,firstObsItr->first.systemChar());
362  cout << "-" << setw(3)
363  << (static_cast<YDSTime>(firstDiffItr->time))
364  << ' ' << setw(2) << firstObsItr->first << ' ';
365  for (const auto& romIt : intersectRom[sysString])
366  {
367  size_t idx1 = header1.getObsIndex(sysString, romIt);
368  size_t idx2 = header2.getObsIndex(sysString, romIt);
369  cout << setw(15) << setprecision(3) << fixed
370  << (firstObsItr->second[idx1].data -
371  secondObsItr->second[idx2].data)
372  << ' ' << romIt.asString() << ' ';
373  }
374  firstObsItr++;
375  secondObsItr++;
376  }
377  // Only file 1 has data for that satellite
378  else if ((firstObsItr != firstDiffItr->obs.end()) &&
379  ((secondObsItr == secondDiffItr->obs.end()) ||
380  (firstObsItr->first.id < secondObsItr->first.id)))
381  {
382  string sysString = string(1,firstObsItr->first.systemChar());
383  cout << "<" << setw(3)
384  << (static_cast<YDSTime>(firstDiffItr->time))
385  << ' ' << setw(2) << firstObsItr->first << ' ';
386  for (const auto& romIt : intersectRom[sysString])
387  {
388  size_t idx = header1.getObsIndex(sysString, romIt);
389  cout << setw(15) << setprecision(3) << fixed
390  << firstObsItr->second[idx].data << ' '
391  << romIt.asString() << ' ';
392  }
393  firstObsItr++;
394  }
395  // Only file 2 has data for that satellite
396  else if (secondObsItr != secondDiffItr->obs.end())
397  {
398  string sysString = string(1,secondObsItr->first.systemChar());
399  cout << ">" << setw(3)
400  << (static_cast<YDSTime>(secondDiffItr->time))
401  << ' ' << setw(2) << secondObsItr->first << ' ';
402  for (const auto& romIt : intersectRom[sysString])
403  {
404  size_t idx = header2.getObsIndex(sysString, romIt);
405  cout << setw(15) << setprecision(3) << fixed
406  << secondObsItr->second[idx].data << ' '
407  << romIt.asString() << ' ';
408  }
409  secondObsItr++;
410  }
411  cout << endl;
412  }
413 
414  firstDiffItr++;
415  secondDiffItr++;
416  }
417  }
418 }
419 
420 int main(int argc, char* argv[])
421 {
422 #include "NewNavInit.h"
423  try
424  {
425  ROWDiff m(argv[0]);
426  if (!m.initialize(argc, argv))
427  return m.exitCode;
428  if (!m.run())
429  return m.exitCode;
430 
431  return m.exitCode;
432  }
433  catch(Exception& e)
434  {
435  cout << e << endl;
436  }
437  catch(std::exception& e)
438  {
439  cout << e.what() << endl;
440  }
441  catch(...)
442  {
443  cout << "unknown error" << endl;
444  }
445  // only reach this point if an exception was caught
446  return BasicFramework::EXCEPTION_ERROR;
447 }
gnsstk::FileFilterFrameWithHeader
Definition: FileFilterFrameWithHeader.hpp:74
ROWDiff::precision
int precision
Definition: rowdiff.cpp:131
main
int main(int argc, char *argv[])
Definition: rowdiff.cpp:420
gnsstk::YDSTime
Definition: YDSTime.hpp:58
gnsstk::Rinex3ObsHeader
Definition: Rinex3ObsHeader.hpp:155
gnsstk::Exception::what
std::string what() const
Dump to a string.
Definition: Exception.cpp:193
gnsstk::FileFilterFrameWithHeader::frontHeader
FileHeader & frontHeader()
Definition: FileFilterFrameWithHeader.hpp:393
gnsstk::CommandOptionWithAnyArg
Definition: CommandOption.hpp:342
gnsstk::Rinex3ObsHeader::prepareVer2Write
void prepareVer2Write(void)
Definition: Rinex3ObsHeader.cpp:2141
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::Rinex3ObsHeader::mapObsTypes
RinexObsMap mapObsTypes
SYS / # / OBS TYPES.
Definition: Rinex3ObsHeader.hpp:519
ROWDiff::process
virtual void process()
Definition: rowdiff.cpp:152
gnsstk::Exception
Definition: Exception.hpp:151
initialize
int initialize(string &errors)
Definition: RinEdit.cpp:513
ROWDiff::initialize
virtual bool initialize(int argc, char *argv[])
Definition: rowdiff.cpp:135
gnsstk::Rinex3ObsHeader::RinexObsVec
std::vector< RinexObsID > RinexObsVec
Vector of obervables.
Definition: Rinex3ObsHeader.hpp:338
ROWDiff::ROWDiff
ROWDiff(char *arg0)
Definition: rowdiff.cpp:119
gnsstk::Rinex3ObsStream
Definition: Rinex3ObsStream.hpp:65
ROWDiff
Definition: rowdiff.cpp:112
gnsstk::Rinex3ObsDataOperatorLessThanFull
Definition: Rinex3ObsFilterOperators.hpp:67
std
Definition: Angle.hpp:142
gnsstk::FileFilterFrameWithHeader::emptyHeader
bool emptyHeader() const
Definition: FileFilterFrameWithHeader.hpp:277
gnsstk::FileFilterFrameWithHeader::halfDiff
std::list< FileData > halfDiff(const FileFilterFrameWithHeader< FileStream, FileData, FileHeader > &r, BinaryPredicate p, int precision) const
Returns a list of the data in *this that isn't in r.
Definition: FileFilterFrameWithHeader.hpp:198
ROWDiff::precisionOption
gnsstk::CommandOptionWithAnyArg precisionOption
Definition: rowdiff.cpp:128
gnsstk::Rinex3ObsHeader::RinexObsMap
std::map< std::string, RinexObsVec > RinexObsMap
Definition: Rinex3ObsHeader.hpp:342


gnsstk
Author(s):
autogenerated on Wed Oct 25 2023 02:40:41