SatPassUtilities.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 
40 
41 #include <algorithm>
42 
43 #include "Stats.hpp"
44 #include "logstream.hpp"
45 #include "stl_helpers.hpp"
46 
47 #include "Rinex3ObsData.hpp"
48 #include "Rinex3ObsStream.hpp"
49 #include "RinexObsStream.hpp"
50 #include "SatPassUtilities.hpp"
51 
52 using namespace std;
53 using namespace gnsstk::StringUtils;
54 
55 namespace gnsstk
56 {
57  // ---------------------------- read and write SatPass lists
58  // ---------------------
59  void dump(vector<SatPass>& SatPassList, ostream& os, bool rev, bool dbug)
60  {
61  try
62  {
63  int i, j, nep;
64  Epoch ttag;
65  map<unsigned int, unsigned int> indexMap;
66  map<unsigned int, unsigned int>::const_iterator kt;
67  vector<string> obstypes;
68  ostringstream oss;
69 
70  // loop over all data in time order, and dump contents
71  // --------------------------------------------------------------------
72  SatPassIterator SPit(SatPassList, rev, dbug);
73  ttag = SPit.getFirstGoodTime();
74  os << "SPL Dump SatPass list "
75  << printTime(ttag, " from " + SatPass::longfmt);
76  ttag = SPit.getLastGoodTime();
77  os << printTime(ttag, " to " + SatPass::longfmt) << " timeRevers is "
78  << (rev ? "T" : "F") << " and debug is " << (dbug ? "T" : "F")
79  << endl;
80 
81  // iterate over the data in time order
82  nep = 0;
83  while (SPit.next(indexMap))
84  {
85  // NB. next() will never return an empty map with non-zero return
86  // value
87  ttag = SatPassList[indexMap.begin()->first].time(
88  indexMap.begin()->second);
89  if (nep == 0)
90  {
91  obstypes = SatPassList[indexMap.begin()->first].getObsTypes();
92  }
93  nep++;
94 
95  // loop over satellites returned in indexMap - pull out data
96  oss.str("");
97  oss << "SPL " << printTime(ttag, SatPass::longfmt);
98 
99  // iterate over the data in time order
100  for (kt = indexMap.begin(); kt != indexMap.end(); kt++)
101  {
102  int ii = kt->first; // index pass
103  int jj = kt->second; // index count (epoch) in the pass
104 
105  os << oss.str() << " " << SatPassList[ii].status() << " "
106  << RinexSatID(SatPassList[ii].getSat()) << " "
107  << SatPassList[ii].getFlag(jj);
108  os << fixed << setprecision(3);
109 
110  for (size_t i = 0; i < obstypes.size(); i++)
111  {
112  os << " " << obstypes[i] << " " << setw(13)
113  << SatPassList[ii].data(jj, obstypes[i]) << " "
114  << SatPassList[ii].LLI(jj, obstypes[i]) << " "
115  << SatPassList[ii].SSI(jj, obstypes[i]);
116  }
117  os << endl;
118 
119  } // end loop over indexMap
120  } // end while loop over SPit.next()
121  os << "SPL End Dump of SatPass list" << endl;
122  }
123  catch (Exception& e)
124  {
125  GNSSTK_RETHROW(e);
126  }
127  } // end dump()
128 
129  /* -----------------------------------------------------------------------------
130  Find millisecond adjusts of the time tag, pseudoranges C1 C2 P1 P2, phases
131  L1 L2. User the handler to print messages, etc.
132  @param input SatPass list for analysis
133  @param return millisecond handler
134  @return number of ms adjusts found */
135  int findMilliseconds(vector<SatPass>& SPList, msecHandler& msh)
136  {
137  try
138  {
139  int i, ii, jj;
140  double data;
141  Epoch ttag;
142  map<unsigned int, unsigned int> indexMap;
143  map<unsigned int, unsigned int>::iterator kt;
144  SatPassIterator SPit(SPList);
145 
146  msh.setDT(SPit.getDT());
147 
148  while (SPit.next(indexMap))
149  {
150  // get the current timetag
151  kt = indexMap.begin();
152  ttag = SPList[kt->first].time(kt->second);
153 
154  // add all the data at this epoch
155  for (kt = indexMap.begin(); kt != indexMap.end(); ++kt)
156  {
157  ii = kt->first;
158  jj = kt->second;
159  SatID sat = SPList[ii].getSat();
160  vector<string> ots = SPList[ii].getObsTypes();
161  // loop over obs types in this SP
162  for (i = 0; i < ots.size(); i++)
163  {
164  if (SPList[ii].hasType(ots[i]))
165  {
166  data = SPList[ii].data(jj, ots[i]);
167  msh.add(ttag, sat, ots[i], data);
168  }
169  }
170  }
171  }
172 
173  // finalize the algorithm
174  msh.afterAddbeforeFix();
175 
176  return msh.getNMS();
177  }
178  catch (Exception& e)
179  {
180  GNSSTK_RETHROW(e);
181  }
182  } // end findMilliseconds()
183 
184  /* -----------------------------------------------------------------------------
185  Remove millisecond adjusts of the time tags and pseudoranges (C1 C2 P1 P2)
186  and phases (L1 L2), given handler passed to earlier call to
187  findMilliseconds(). User the handler to print messages, etc.
188  @param input SatPass list for modification
189  @param message returned from findMilliseconds() */
190  void removeMilliseconds(vector<SatPass>& SPList, msecHandler& msh)
191  {
192  try
193  {
194  int i, ii, jj;
195  double data;
196  Epoch ttag;
197  CommonTime ttagdum;
198  map<unsigned int, unsigned int> indexMap;
199  map<unsigned int, unsigned int>::iterator kt;
200 
201  SatPassIterator SPit(SPList);
202  while (SPit.next(indexMap))
203  {
204  // get the current timetag
205  kt = indexMap.begin();
206  ttag = SPList[kt->first].time(kt->second);
207 
208  // add all the data at this epoch
209  int n(0);
210  double deltfix(0.0);
211  for (kt = indexMap.begin(); kt != indexMap.end(); ++kt)
212  {
213  ii = kt->first;
214  jj = kt->second;
215  SatID sat = SPList[ii].getSat();
216  vector<string> ots = SPList[ii].getObsTypes();
217  // loop over obs types in this SP
218  for (i = 0; i < ots.size(); i++)
219  {
220  if (SPList[ii].hasType(ots[i]))
221  {
222  data = SPList[ii].data(jj, ots[i]);
223  // tricky - don't keep correcting ttag
224  ttagdum = static_cast<CommonTime>(ttag);
225  msh.fix(ttagdum, sat, ots[i], data);
226  SPList[ii].data(jj, ots[i]) = data;
227  if (++n == 1)
228  {
229  deltfix = (ttagdum - ttag); // only once
230  }
231  }
232  }
233  // correct time tag for this SP
234  if (n > 0 && deltfix != 0.0)
235  {
236  SPList[ii].timeoffset(jj) += deltfix;
237  }
238  }
239  }
240 
241  // LOG(INFO) << msh.getFixMessage(verbose);
242  }
243  catch (Exception& e)
244  {
245  GNSSTK_RETHROW(e);
246  }
247  } // end removeMilliseconds()
248 
249  // -----------------------------------------------------------------------------
250  // prototype is in SatPass.hpp as a friend
251  int SatPassFromRinexFiles(vector<string>& filenames,
252  vector<string>& obstypes, double dtin,
253  vector<SatPass>& SPList, vector<RinexSatID> exSats,
254  bool lenient, Epoch beginTime, Epoch endTime)
255  {
256  try
257  {
258  if (filenames.size() == 0)
259  {
260  return -1;
261  }
262 
263  // sort the file names on the begin time in the header
264  if (filenames.size() > 1)
265  {
266  sortRinexObsFiles(filenames);
267  }
268 
269  int i, j, nfiles(0), nepochs(0);
270  ostringstream oss;
271  unsigned short flag;
272  vector<double> data(obstypes.size(), 0.0);
273  vector<unsigned short> ssi(obstypes.size(), 0);
274  vector<unsigned short> lli(obstypes.size(), 0);
275  map<RinexSatID, int> indexForSat;
276  map<RinexSatID, int>::const_iterator satit;
278  RinexObsData obsdata;
279  const string timfmt(
280  string("%F %10.3g = %04Y/%02m/%02d %02H:%02M:%02S"));
281 
282  // must make > 1millisec, but small enough to catch e.g. 1sec data
283  const double dttol(0.01); // TD ??
284 
285  // estimate the data timestep
286  const int estN(9);
287  const double esttol(0.01);
288  int estn[estN] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
289  double dt, estdt[estN];
291  // records out of time order
292  bool onOrder(false), onShort(false);
293  vector<int> nOrder, nShort;
294  vector<Epoch> timeOrder, timeShort;
295 
296  // sort existing list on begin time
297  std::sort(SPList.begin(), SPList.end());
298 
299  /* fill the index array using SatPass's already there
300  assumes SPList is in time order - later ones overwrite earlier */
301  for (i = 0; i < SPList.size(); i++)
302  indexForSat[SPList[i].getSat()] = i;
303 
304  // loop over file names
305  for (int nfile = 0; nfile < filenames.size(); nfile++)
306  {
307  string filename = filenames[nfile];
308 
309  // does the file exist?
310  RinexObsStream RinFile(filename.c_str());
311  if (filename.empty() || !RinFile)
312  {
313  // cerr << "Error: input file " << filename << " does not
314  // exist.\n";
315  continue;
316  }
317  RinFile.exceptions(fstream::failbit);
318  // RinFile.beLenient(lenient);
319 
320  // is it a Rinex Obs file? ... read the header
321  try
322  {
323  RinFile >> header;
324  }
325  catch (Exception& e)
326  {
327  // cerr << "Error: input file " << filename << " is not a Rinex
328  // obs file\n";
329  continue;
330  }
331 
332  // to return the number of files read
333  nfiles++;
334 
335  /* warn if lenient RINEX did something
336  if(!header.whatLenient.empty())
337  oss << " Warning - changes were made by lenient RINEX reader: "
338  << header.whatLenient << endl; */
339 
340  // check that obs types are in header - first file only
341  if (obstypes.size() == 0)
342  {
343  for (j = 0; j < header.obsTypeList.size(); j++)
344  {
345  obstypes.push_back(
346  RinexObsHeader::convertObsType(header.obsTypeList[j]));
347  }
348  data = vector<double>(obstypes.size(), 0.0);
349  ssi = vector<unsigned short>(obstypes.size(), 0);
350  lli = vector<unsigned short>(obstypes.size(), 0);
351  }
352  // NB do not change obstypes past this, but may create newobstypes
353 
354  // loop over epochs in the file
355  while (1)
356  {
357  try
358  {
359  RinFile >> obsdata;
360  }
361  catch (Exception& e)
362  {
363  LOG(ERROR)
364  << "Reading RINEX obs threw exception " << e.what();
365  GNSSTK_RETHROW(e);
366  }
367 
368  if (RinFile.eof() || !RinFile.good())
369  {
370  break;
371  }
372 
373  RinexObsData::RinexSatMap::const_iterator it;
374  RinexObsData::RinexObsTypeMap::const_iterator jt;
375 
376  // test time limits
377  if (obsdata.time < beginTime)
378  {
379  continue;
380  }
381  if (obsdata.time > endTime)
382  {
383  break;
384  }
385 
386  /* lenient readers
387  if(!obsdata.whatLenient.empty())
388  oss << " Warning - lenient RINEX reader at "
389  << printTime(obsdata.time,"%04Y/%02m/%02d %02H:%02M:%02S:
390  ")
391  << obsdata.whatLenient << endl; */
392 
393  // skip auxiliary header, etc
394  if (obsdata.epochFlag != 0 && obsdata.epochFlag != 1)
395  {
396  continue;
397  }
398 
399  if (prevtime != CommonTime::BEGINNING_OF_TIME)
400  {
401  // compute time since the last epoch
402  dt = obsdata.time - prevtime;
403 
404  if (dt > dttol)
405  { // positive dt only
406  if (::fabs(::fmod(dt, dtin)) > dttol)
407  {
408  if (lenient)
409  {
410  // NB this is just decimation ...
411  if (!onShort)
412  {
413  nShort.push_back(0);
414  timeShort.push_back(prevtime);
415  onShort = true;
416  }
417  nShort[nShort.size() - 1]++;
418  continue;
419  }
420  else
421  {
423  string("Invalid time step: expected ") +
424  asString<double>(dtin) +
425  string(" seconds but found ") +
426  asString<double>(dt) + string(" at time ") +
427  printTime(obsdata.time, timfmt)));
428  }
429  }
430 
431  for (j = 0; j < estN; j++)
432  {
433  if (estn[j] <= 0)
434  {
435  estdt[j] = dt;
436  estn[j] = 1;
437  break;
438  } // first one
439  if (::fabs(dt - estdt[j]) < esttol)
440  {
441  estn[j]++;
442  break;
443  } // matches j
444  if (j == estN - 1)
445  { // running out of room
446  int jj, kk(0), nleast(estn[0]);
447  for (jj = 1; jj < estN; jj++)
448  { // find the least common dt
449  if (estn[jj] <= nleast)
450  {
451  kk = jj;
452  nleast = estn[jj];
453  }
454  }
455  estn[kk] = 1;
456  estdt[kk] = dt; // replace it
457  }
458  }
459  }
460  else if (dt < dttol)
461  { // negative, and positive but tiny (< dttol)
462  if (lenient)
463  {
464  if (!onOrder)
465  {
466  nOrder.push_back(0);
467  timeOrder.push_back(prevtime);
468  onOrder = true;
469  }
470  nOrder[nOrder.size() - 1]++;
471  continue;
472  }
473  else
474  {
476  string("Invalid time step: expected ") +
477  asString<double>(dtin) +
478  string(" seconds but found ") +
479  asString<double>(dt) + string(" at time ") +
480  printTime(obsdata.time, "%4F %10.3g")));
481  }
482  }
483  }
484  onOrder = onShort = false;
485  prevtime = obsdata.time;
486 
487  // loop over satellites
488  for (it = obsdata.obs.begin(); it != obsdata.obs.end(); ++it)
489  {
490  RinexSatID sat = it->first;
491  flag = SatPass::OK;
492 
493  // exclude sats
494  if (vectorindex(exSats, sat) != -1)
495  {
496  continue;
497  }
498  if (vectorindex(exSats, RinexSatID(-1, sat.system)) != -1)
499  {
500  continue;
501  }
502 
503  // loop over obs
504  for (j = 0; j < obstypes.size(); j++)
505  {
506  if ((jt = it->second.find(RinexObsHeader::convertObsType(
507  obstypes[j]))) == it->second.end())
508  {
509  data[j] = 0.0;
510  lli[j] = ssi[j] = 0;
511  // don't do this b/c SatPass may have empty obs types
512  // flag = SatPass::BAD;
513  }
514  else
515  {
516  data[j] = jt->second.data;
517  lli[j] = jt->second.lli;
518  ssi[j] = jt->second.ssi;
519  // NB - some obstypes are missing on some sats;
520  // thus ngood applies to ALL obstypes
521  if (data[j] == 0.0)
522  {
523  flag = SatPass::BAD;
524  }
525  }
526  } // end loop over obs
527 
528  // find the current SatPass for this sat
529  satit = indexForSat.find(sat);
530 
531  // if there is not a pass for this satellite, create one
532  if (satit == indexForSat.end())
533  {
534  SatPass newSP(sat, dtin, obstypes);
535  SPList.push_back(newSP);
536  indexForSat[sat] = SPList.size() - 1;
537  satit = indexForSat.find(sat);
538  }
539 
540  // add the data to the SatPass
541  do
542  {
543  i = SPList[satit->second].addData(obsdata.time, obstypes,
544  data, lli, ssi, flag);
545  if (i == -1)
546  { // gap
547  SatPass newSP(sat, dtin, obstypes);
548  SPList.push_back(newSP);
549  indexForSat[sat] = SPList.size() - 1;
550  satit = indexForSat.find(sat);
551  // repeat
552  }
553 
554  // handle most above, but still may be problems eg between
555  // files
556  else if (i == -2)
557  { // time tag out of order
558  Exception e(
559  "Timetags out of order in RINEX file " + filename +
560  " at time " + printTime(obsdata.time, timfmt) +
561  (lenient ? " - Error, this should not happen!"
562  : ""));
563  GNSSTK_THROW(e);
564  }
565 
566  // else if(i == -3) { // sat not found (RinexObsData form
567  // only)
568  //}
569 
570  } while (i == -1);
571 
572  } // end loop over satellites
573  nepochs++;
574 
575  if (timeShort.size() > 50 && timeShort.size() > nepochs / 2)
576  {
577  for (i = 0; i < timeOrder.size(); i++)
578  LOG(WARNING) << "Warning - " << setw(4) << nOrder[i]
579  << " data records following epoch "
580  << printTime(timeOrder[i], timfmt)
581  << " are out of time order";
582  LOG(ERROR) << "ERROR - too many 'short timestep' warnings - "
583  << "decimate the data file first.";
584  GNSSTK_THROW(
585  Exception("Too many short timesteps - decimate instead"));
586  }
587 
588  } // end loop over obs data in file
589 
590  RinFile.close();
591 
592  } // end loop over RINEX files
593 
594  // find the most common timestep
595  for (j = 0, i = 1; i < estN; i++)
596  if (estn[i] > estn[j])
597  {
598  j = i;
599  }
600  dt = estdt[j];
601 
602  // is there disagreement? throw if there is; SatPass must have correct
603  // dt
604  if (::fabs(dt - dtin) > esttol)
605  {
606  GNSSTK_THROW(Exception("Input time step (" + asString(dtin, 2) +
607  ") does not match computed (" +
608  asString(dt, 2) + ")"));
609  }
610 
611  string msg = oss.str();
612  if (!msg.empty())
613  {
614  stripTrailing(msg, '\n');
615  stripTrailing(msg, '\r');
616  LOG(WARNING) << msg;
617  }
618  if (timeShort.size() > 0)
619  {
620  for (i = 0; i < timeShort.size(); i++)
621  LOG(WARNING) << "Warning - " << setw(4) << nShort[i]
622  << " data records following epoch "
623  << printTime(timeShort[i], timfmt)
624  << " have short (<" << dtin << "sec) timestep";
625  }
626  if (timeOrder.size() > 0)
627  {
628  for (i = 0; i < timeOrder.size(); i++)
629  LOG(WARNING) << "Warning - " << setw(4) << nOrder[i]
630  << " data records following epoch "
631  << printTime(timeOrder[i], timfmt)
632  << " are out of time order";
633  }
634 
635  return nfiles;
636  }
637  catch (Exception& e)
638  {
639  GNSSTK_RETHROW(e);
640  }
641  }
642 
643  // -----------------------------------------------------------------------------
644  // note this only works if the passes all have the same OTs in the same order.
645  int SatPassToRinex2File(const string& filename, RinexObsHeader& header,
646  vector<SatPass>& SPList)
647  {
648  try
649  {
650  if (filename.empty())
651  {
652  return 0;
653  }
654 
655  int i, j, ii, jj, ngood;
656  double data;
657  vector<string> obstypes, ots;
658  map<unsigned int, unsigned int> indexMap;
659  map<unsigned int, unsigned int>::const_iterator kt;
660  RinexObsData robs;
661  // RinexObsData::RinexSatMap::const_iterator it;
662  // RinexObsData::RinexObsTypeMap::const_iterator jt;
663 
664  // open file
665  RinexObsStream rstrm(filename.c_str(), ios::out);
666  if (!rstrm)
667  {
668  return -1;
669  }
670  rstrm.exceptions(fstream::failbit);
671 
672  // create a master list of obstypes - union of all passes
673  for (i = 0; i < SPList.size(); i++)
674  {
675  ots = SPList[i].getObsTypes();
676  for (j = 0; j < ots.size(); j++)
677  {
678  if (vectorindex(obstypes, ots[j]) == -1)
679  {
680  obstypes.push_back(ots[j]);
681  }
682  }
683  }
684 
685  // is there a change?
686  bool change(obstypes.size() != header.obsTypeList.size());
687  if (!change)
688  {
689  for (i = 0; i < obstypes.size(); i++)
690  {
691  if (obstypes[i] !=
692  RinexObsHeader::convertObsType(header.obsTypeList[i]))
693  {
694  change = true;
695  break;
696  }
697  }
698  }
699 
700  // put these obstypes in the header
701  if (change)
702  {
703  header.obsTypeList.clear();
704  for (i = 0; i < obstypes.size(); i++)
705  {
706  header.obsTypeList.push_back(
707  RinexObsHeader::convertObsType(obstypes[i]));
708  }
709 
710  // must remove the table
711  header.numObsForSat.clear();
712  header.valid ^= RinexObsHeader::prnObsValid;
713  }
714 
715  // create the iterator
716  SatPassIterator spit(SPList);
717 
718  // put obs types, first time and interval in header
719  header.firstObs = spit.getFirstTime();
720  header.lastObs = spit.getLastTime();
721  header.interval = spit.getDT();
722  header.valid |= RinexObsHeader::firstTimeValid;
723  header.valid |= RinexObsHeader::lastTimeValid;
724  header.valid |= RinexObsHeader::intervalValid;
725 
726  rstrm << header;
727 
728  while (spit.next(indexMap))
729  {
730  robs.obs.clear();
731  robs.numSvs = 0;
732  robs.clockOffset = 0.0;
733 
734  kt = indexMap.begin();
735  robs.time = SPList[kt->first].time(kt->second);
736 
737  for (kt = indexMap.begin(); kt != indexMap.end(); ++kt)
738  {
739  ii = kt->first;
740  jj = kt->second;
741  if (SPList[ii].status() == -1)
742  {
743  continue;
744  }
745  SatID sat = SPList[ii].getSat();
747  for (ngood = 0, j = 0; j < header.obsTypeList.size(); j++)
748  {
749  RinexDatum rd;
750 
751  if (SPList[ii].getFlag(jj) != SatPass::BAD &&
752  SPList[ii].hasType(obstypes[j]))
753  {
754  rd.data = SPList[ii].data(jj, obstypes[j]);
755  ngood++;
756  }
757  // else rd is all zeros
758 
759  rotm.insert(map<RinexObsType, RinexDatum>::value_type(
760  header.obsTypeList[j], rd));
761  }
762  if (ngood > 0)
763  {
764  robs.obs.insert(
765  map<SatID, RinexObsData::RinexObsTypeMap>::value_type(
766  sat, rotm));
767  robs.numSvs++;
768  }
769  }
770 
771  if (robs.numSvs == 0)
772  {
773  continue;
774  }
775 
776  robs.epochFlag = 0;
777  rstrm << robs;
778  }
779 
780  rstrm.close();
781  }
782  catch (Exception& e)
783  {
784  GNSSTK_RETHROW(e);
785  }
786 
787  return 0;
788  }
789 
790  /* -----------------------------------------------------------------------------
791  Iterate over the input vector of SatPass objects (sorted to be in time
792  order) and write them, with the given header, to a RINEX VER 3 observation
793  file of the given filename. return -1 if the file could not be opened,
794  otherwise return 0. */
795  int SatPassToRinex3File(const string& filename, const Rinex3ObsHeader& headerIn,
796  const map<char, vector<string>>& sysobs,
797  vector<SatPass>& SPList)
798  {
799  try
800  {
801  if (filename.empty())
802  {
803  return 0;
804  }
805 
806  int i, j, ii, jj, ngood;
807  vector<string> obstypes;
808  map<unsigned int, unsigned int> indexMap;
809  map<unsigned int, unsigned int>::const_iterator kt;
810  Rinex3ObsData robs;
811 
812  // open file
813  Rinex3ObsStream rstrm(filename.c_str(), ios::out);
814  if (!rstrm.is_open())
815  {
816  return -1;
817  }
818 
819  rstrm.exceptions(fstream::failbit);
820 
821  // create a new header
822  Rinex3ObsHeader header(headerIn);
823  // header.commentList.push_back(string("Written by
824  // SatPassToRinex3File"));
825 
826  if (header.version < 3)
827  {
828  // create a master list of obstypes - union of all passes
829  for (i = 0; i < SPList.size(); i++)
830  {
831  vector<string> ots(SPList[i].getObsTypes());
832  for (j = 0; j < ots.size(); j++)
833  {
834  if (vectorindex(obstypes, ots[j]) == -1)
835  {
836  obstypes.push_back(ots[j]);
837  }
838  }
839  }
840 
841  // clear R2 obs types and replace
842  header.R2ObsTypes.clear();
843  // obstypes = SPList[0].getObstypes(); // SatPass == R2 obstypes
844  // (L1L2P1P2)
845  for (i = 0; i < obstypes.size(); i++)
846  {
847  header.R2ObsTypes.push_back(obstypes[i]);
848  }
849  }
850 
851  /* define R3 ObsIDs for each system
852  map<string sys char, vec<ObsID> > */
853  header.mapObsTypes.clear();
854  map<char, vector<string>>::const_iterator it;
855  for (it = sysobs.begin(); it != sysobs.end(); ++it)
856  {
857  vector<RinexObsID> v;
858  string sysstr(string(1, it->first));
859  header.mapObsTypes[sysstr] = v;
860  for (j = 0; j < it->second.size(); j++)
861  {
862  RinexObsID roid(it->second[j], header.version);
863  header.mapObsTypes[sysstr].push_back(roid);
864  }
865  }
866 
867  // create the iterator
868  SatPassIterator spit(SPList);
869 
870  // put obs types, first time and interval in header
871  header.firstObs = static_cast<CivilTime>(spit.getFirstTime());
872  header.lastObs = static_cast<CivilTime>(spit.getLastTime());
873  header.interval = spit.getDT();
874  header.valid |= Rinex3ObsHeader::validFirstTime;
875  header.valid |= Rinex3ObsHeader::validLastTime;
876  header.valid |= Rinex3ObsHeader::validInterval;
877 
878  rstrm << header;
879 
880  while (spit.next(indexMap))
881  {
882  robs.obs.clear();
883  robs.epochFlag = 0;
884  robs.numSVs = 0;
885  robs.clockOffset = 0.0;
886 
887  kt = indexMap.begin();
888  robs.time = SPList[kt->first].time(kt->second);
889 
890  for (kt = indexMap.begin(); kt != indexMap.end(); ++kt)
891  {
892  ii = kt->first;
893  jj = kt->second;
894  if (SPList[ii].status() == -1)
895  {
896  continue; // skip bad passes
897  }
898  RinexSatID sat = SPList[ii].getSat(); // get sat
899 
900  /* in R2, obstypes are defined above, a superset of all
901  systems/passes in R3, obstypes are defined per system/pass */
902  if (header.version >= 3)
903  {
904  obstypes = SPList[ii].getObstypes();
905  }
906 
907  vector<RinexDatum> vRD;
908  for (ngood = 0, j = 0; j < obstypes.size(); j++)
909  {
910  RinexDatum rd;
911 
912  if (SPList[ii].getFlag(jj) != SatPass::BAD &&
913  SPList[ii].hasType(obstypes[j]))
914  {
915  rd.data = SPList[ii].data(jj, obstypes[j]);
916  // rd.ssi = ?;
917  // rd.lli = ?;
918  ngood++;
919  }
920 
921  // save it in vector - zero or not
922  vRD.push_back(rd);
923  }
924 
925  if (ngood > 0)
926  {
927  robs.obs.insert(
928  map<RinexSatID, vector<RinexDatum>>::value_type(sat, vRD));
929  robs.numSVs++;
930  }
931  }
932 
933  if (robs.numSVs == 0)
934  {
935  continue;
936  }
937 
938  rstrm << robs;
939  }
940 
941  rstrm.close();
942  }
943  catch (Exception& e)
944  {
945  GNSSTK_RETHROW(e);
946  }
947 
948  return 0;
949  }
950 
951 } // namespace gnsstk
952 
953 // -------------------------------------------------------------------------------
954 // -------------------------------------------------------------------------------
gnsstk::RinexObsStream
Definition: RinexObsStream.hpp:67
gnsstk::dump
void dump(vector< SatPass > &SatPassList, ostream &os, bool rev, bool dbug)
Definition: SatPassUtilities.cpp:59
example3.header
header
Definition: example3.py:22
gnsstk::RinexDatum
Storage for single RINEX OBS data measurements.
Definition: RinexDatum.hpp:55
gnsstk::BEGINNING_OF_TIME
const Epoch BEGINNING_OF_TIME(CommonTime::BEGINNING_OF_TIME)
Earliest representable Epoch.
gnsstk::Rinex3ObsHeader
Definition: Rinex3ObsHeader.hpp:155
gnsstk::Rinex3ObsData::obs
DataMap obs
the map of observations
Definition: Rinex3ObsData.hpp:114
stl_helpers.hpp
gnsstk::msecHandler::fix
void fix(CommonTime &ttag, const SatID sat, const std::string obstype, double &data)
Definition: msecHandler.cpp:214
gnsstk::msecHandler::getNMS
int getNMS()
get number of valid adjusts found
Definition: msecHandler.hpp:178
gnsstk::RinexObsData::obs
RinexSatMap obs
the map of observations
Definition: RinexObsData.hpp:95
gnsstk::Exception::what
std::string what() const
Dump to a string.
Definition: Exception.cpp:193
gnsstk::Epoch::second
double second() const
Get seconds of minute.
Definition: Epoch.hpp:782
gnsstk::msecHandler
Definition: msecHandler.hpp:66
gnsstk::SatID
Definition: SatID.hpp:89
RinexObsStream.hpp
logstream.hpp
gnsstk::StringUtils::asString
std::string asString(IonexStoreStrategy e)
Convert a IonexStoreStrategy to a whitespace-free string name.
Definition: IonexStoreStrategy.cpp:46
gnsstk::Rinex3ObsData::numSVs
short numSVs
Definition: Rinex3ObsData.hpp:109
gnsstk::SatPass
Definition: SatPass.hpp:71
gnsstk::SatPassIterator::getLastGoodTime
Epoch getLastGoodTime() const
Definition: SatPassIterator.hpp:124
gnsstk::RinexDatum::data
double data
The actual data point.
Definition: RinexDatum.hpp:76
gnsstk::WARNING
@ WARNING
Definition: logstream.hpp:57
gnsstk::msecHandler::add
void add(CommonTime ttag, const SatID sat, const std::string obstype, double data)
Definition: msecHandler.cpp:124
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::RinexObsData::numSvs
short numSvs
Definition: RinexObsData.hpp:93
gnsstk::Rinex3ObsData::epochFlag
short epochFlag
Definition: Rinex3ObsData.hpp:104
Stats.hpp
gnsstk::Exception
Definition: Exception.hpp:151
gnsstk::SatPassIterator::getFirstGoodTime
Epoch getFirstGoodTime() const
Definition: SatPassIterator.hpp:112
gnsstk::removeMilliseconds
void removeMilliseconds(vector< SatPass > &SPList, msecHandler &msh)
Definition: SatPassUtilities.cpp:190
gnsstk::StringUtils::stripTrailing
std::string & stripTrailing(std::string &s, const std::string &aString, std::string::size_type num=std::string::npos)
Definition: StringUtils.hpp:1453
gnsstk::SatPassToRinex2File
int SatPassToRinex2File(const string &filename, RinexObsHeader &header, vector< SatPass > &SPList)
Definition: SatPassUtilities.cpp:645
gnsstk::RinexObsData::epochFlag
short epochFlag
Definition: RinexObsData.hpp:89
gnsstk::Rinex3ObsData::time
CommonTime time
Time corresponding to the observations.
Definition: Rinex3ObsData.hpp:91
gnsstk::ERROR
@ ERROR
Definition: logstream.hpp:57
gnsstk::SatPassIterator::getFirstTime
Epoch getFirstTime()
Get the first (earliest) time found in the SatPass list.
Definition: SatPassIterator.hpp:106
gnsstk::CommonTime
Definition: CommonTime.hpp:84
gnsstk::Rinex3ObsData
Definition: Rinex3ObsData.hpp:75
gnsstk::RinexObsData::clockOffset
double clockOffset
optional clock offset
Definition: RinexObsData.hpp:94
gnsstk::RinexObsID
Definition: RinexObsID.hpp:102
Rinex3ObsData.hpp
GNSSTK_RETHROW
#define GNSSTK_RETHROW(exc)
Definition: Exception.hpp:369
gnsstk::SatID::system
SatelliteSystem system
System for this satellite.
Definition: SatID.hpp:156
gnsstk::msecHandler::setDT
void setDT(double dt_in)
must set the nominal timestep before any add() or fix()
Definition: msecHandler.hpp:142
gnsstk::Rinex3ObsStream
Definition: Rinex3ObsStream.hpp:65
gnsstk::SatPassIterator::getDT
double getDT()
Get the time interval, which is common to all the SatPass in the list.
Definition: SatPassIterator.hpp:136
example3.data
data
Definition: example3.py:22
gnsstk::Rinex3ObsData::clockOffset
double clockOffset
optional clock offset in seconds
Definition: Rinex3ObsData.hpp:112
example6.ssi
ssi
Definition: example6.py:124
gnsstk::CivilTime
Definition: CivilTime.hpp:55
gnsstk::SatPassIterator::next
int next(std::map< unsigned int, unsigned int > &indexMap)
Definition: SatPassIterator.cpp:190
gnsstk::RinexObsData::RinexObsTypeMap
std::map< RinexObsType, gnsstk::RinexDatum > RinexObsTypeMap
map from RinexObsType to RinexDatum.
Definition: RinexObsData.hpp:73
gnsstk::StringUtils
Definition: IonexStoreStrategy.cpp:44
Rinex3ObsStream.hpp
LOG
#define LOG(level)
define the macro that is used to write to the log stream
Definition: logstream.hpp:315
gnsstk::SatPassToRinex3File
int SatPassToRinex3File(const string &filename, const Rinex3ObsHeader &headerIn, const map< char, vector< string >> &sysobs, vector< SatPass > &SPList)
Definition: SatPassUtilities.cpp:795
gnsstk::printTime
std::string printTime(const CommonTime &t, const std::string &fmt)
Definition: TimeString.cpp:64
gnsstk::RinexSatID
Definition: RinexSatID.hpp:63
SatPassUtilities.hpp
std
Definition: Angle.hpp:142
gnsstk::SatPassIterator::getLastTime
Epoch getLastTime()
Get the last (latest) time found in the SatPass list.
Definition: SatPassIterator.hpp:109
gnsstk::StringUtils::change
std::string change(const std::string &aString, const std::string &inputString, const std::string &outputString, std::string::size_type startPos=0, unsigned numChanges=(std::numeric_limits< unsigned >().max()))
Definition: StringUtils.hpp:1521
gnsstk::SatPassIterator
Definition: SatPassIterator.hpp:55
gnsstk::sortRinexObsFiles
string sortRinexObsFiles(vector< string > &files)
Definition: RinexUtilities.cpp:347
gnsstk::Epoch
Definition: Epoch.hpp:123
GNSSTK_THROW
#define GNSSTK_THROW(exc)
Definition: Exception.hpp:366
gnsstk::SatPassFromRinexFiles
int SatPassFromRinexFiles(vector< string > &filenames, vector< string > &obstypes, double dtin, vector< SatPass > &SPList, vector< RinexSatID > exSats, bool lenient, Epoch beginTime, Epoch endTime)
Definition: SatPassUtilities.cpp:251
gnsstk::RinexObsHeader
Definition: RinexObsHeader.hpp:107
example6.lli
lli
Definition: example6.py:123
gnsstk::RinexObsData
Definition: RinexObsData.hpp:68
gnsstk::msecHandler::afterAddbeforeFix
int afterAddbeforeFix()
Definition: msecHandler.cpp:170
gnsstk::vectorindex
int vectorindex(const std::vector< T > &vec, const T &value)
Definition: stl_helpers.hpp:123
gnsstk::RinexObsData::time
gnsstk::CommonTime time
the time corresponding to the observations
Definition: RinexObsData.hpp:77
gnsstk::findMilliseconds
int findMilliseconds(vector< SatPass > &SPList, msecHandler &msh)
Definition: SatPassUtilities.cpp:135


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