1 //==============================================================================
2 //
3 //  This file is part of GPSTk, the GPS Toolkit.
4 //
5 //  The GPSTk 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 GPSTk 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 GPSTk; 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-2020, 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 
39 /**
40  * @file Rinex3ObsHeader.hpp
41  * Encapsulate header of Rinex observation file, including I/O
42  */
43 
44 #ifndef GPSTK_RINEX3OBSHEADER_HPP
45 #define GPSTK_RINEX3OBSHEADER_HPP
46 
47 #include <vector>
48 #include <list>
49 #include <map>
50 #include <set>
51 #include <iostream>
52 #include <iomanip>
53 
54 #include "CivilTime.hpp"
55 #include "FFStream.hpp"
56 #include "Rinex3ObsBase.hpp"
57 #include "Triple.hpp"
58 #include "RinexSatID.hpp"
59 #include "RinexObsID.hpp"
60 
61 
62 namespace gpstk
63 {
64 
65       /// @ingroup FileHandling
66       //@{
67 
68       /** @page rinobshead RINEX OBS header implementation
69        *
70        * For each header line type, the following are listed in the
71        * table below:
72        *   1. The label
73        *   2. Its usage in RINEX 2
74        *   3. Its usage in RINEX 3
75        *   4. The name for validity checking and header variable
76        *      storage (see below)
77        *   5. Variables (data members) storing the header information
78        *
79        * | Header Field         | v2  | v3  | Name              | Variables         |
80        * | :------------------- | :-- | :-- | :---------------- | :---------------- |
81        * | RINEX VERSION / TYPE | req | req | Version           | version           |
82        * |                    ^ |   ^ |   ^ |                 ^ | fileType          |
83        * |                    ^ |   ^ |   ^ |                 ^ | fileSys           |
84        * |                    ^ |   ^ |   ^ |                 ^ | fileSysSat        |
85        * |                    ^ |   ^ |   ^ |                 ^ | preserveVerType   |
86        * | PGM / RUN BY / DATE  | req | req | RunBy             | fileProgram       |
87        * |                    ^ |   ^ |   ^ |                 ^ | fileAgency        |
88        * |                    ^ |   ^ |   ^ |                 ^ | date              |
89        * |                    ^ |   ^ |   ^ |                 ^ | preserveDate      |
90        * | COMMENT              | opt | opt | Comment           | commentList       |
91        * | MARKER NAME          | req | opt | MarkerName        | markerName        |
92        * | MARKER NUMBER        | opt | opt | MarkerNumber      | markerNumber      |
93        * | MARKER TYPE          |  -  | req | MarkerType        | markerType        |
94        * | OBSERVER / AGENCY    | req | req | Observer          | observer          |
95        * |                    ^ |   ^ |   ^ |                 ^ | agency            |
96        * | REC # / TYPE / VERS  | req | req | Receiver          | recNo             |
97        * |                    ^ |   ^ |   ^ |                 ^ | recType           |
98        * |                    ^ |   ^ |   ^ |                 ^ | recVers           |
99        * | ANT # / TYPE         | req | req | AntennaType       | antNo             |
100        * |                    ^ |   ^ |   ^ |                 ^ | antType           |
101        * | APPROX POSITION XYZ  | req | req | AntennaPosition   | antennaPosition   |
102        * | ANTENNA: DELTA H/E/N | req | req | AntennaDeltaHEN   | antennaDeltaHEN   |
103        * | ANTENNA: DELTA X/Y/Z |  -  | opt | AntennaDeltaXYZ   | antennaDeltaXYZ   |
104        * | ANTENNA: PHASECENTER |  -  | opt | AntennaPhaseCtr   | antennaSatSys     |
105        * |                    ^ |   ^ |   ^ |                 ^ | antennaObsCode    |
106        * |                    ^ |   ^ |   ^ |                 ^ | antennaPhaseCtr   |
107        * | ANTENNA: B.SIGHT XYZ |  -  | opt | AntennaBsightXYZ  | antennaBsightXYZ  |
108        * | ANTENNA: ZERODIR AZI |  -  | opt | AntennaZeroDirAzi | antennaZeroDirAzi |
109        * | ANTENNA: ZERODIR XYZ |  -  | opt | AntennaZeroDirXYZ | antennaZeroDirXYZ |
110        * | CENTER OF MASS: XYZ  |  -  | opt | CenterOfMass      | centerOfMass      |
111        * | # / TYPES OF OBSERV  | req | n/a | NumObs            |                   |
112        * | SYS / # / OBS TYPES  | n/a | req | SystemNumObs      | mapObsTypes       |
113        * | WAVELENGTH FACT L1/2 | opt |  -  | WaveFact          | wavelengthFactor  |
114        * |                    ^ |   ^ |   ^ |                 ^ | extraWaveFactList |
115        * | SIGNAL STRENGTH UNIT |  -  | opt | SigStrengthUnit   | sigStrengthUnit   |
116        * | INTERVAL             | opt | opt | Interval          | interval          |
117        * | TIME OF FIRST OBS    | req | req | FirstTime         | firstObs          |
118        * | TIME OF LAST OBS     | opt | opt | LastTime          | lastObs           |
119        * | RCV CLOCK OFFS APPL  | opt | opt | ReceiverOffset    | receiverOffset    |
120        * | SYS / DCBS APPLIED   |  -  | opt | SystemDCBSapplied | infoDCBS          |
121        * | SYS / PCVS APPLIED   |  -  | opt | SystemPCVSapplied | infoPCVS          |
122        * | SYS / SCALE FACTOR   |  -  | opt | SystemScaleFac    | sysSfacMap        |
123        * | SYS / PHASE SHIFT    |  -  | req | SystemPhaseShift  | sysPhaseShift     |
124        * | GLONASS SLOT / FRQ # |  -  | req | GlonassSlotFreqNo | glonassFreqNo     |
125        * | GLONASS COD/PHS/BIS  |  -  | req | GlonassCodPhsBias | glonassCodPhsBias |
126        * | LEAP SECONDS         | opt | opt | LeapSeconds       | leapSeconds       |
127        * | # OF SATELLITES      | opt | opt | NumSats           | numSVs            |
128        * | PRN / # OF OBS       | opt | opt | PrnObs            | numObsForSat      |
129        * | END OF HEADER        | req | req | EoH (header only) | -                 |
130        *
131        * The "Name" column in the above table is used for both
132        * validity flags and header strings.  For the header strings,
133        * prepend "hs", e.g. "hsVersion" will give you the header field
134        * label.  For validity flags, prepend valid,
135        * e.g. "validVersion" would indicate the presence of the "RINEX
136        * VERSION / TYPE" header record.
137        */
138 
139       /**
140        * This class models the header for a RINEX 3 Observation File.
141        * @sa gpstk::Rinex3ObsData and gpstk::Rinex3ObsStream.
142        * @sa rinex_obs_test.cpp and rinex_obs_read_write.cpp for examples.
143        *
144        * RINEX 2 is also supported.
145        *
146        * @warning This class makes no attempt to apply or remove any
147        * of the phase shifts when converting between RINEX and other
148        * observation types.  This can lead to invalid RINEX OBS data.
149        * Either use RINEX 3.00 which does not require the
150        * SYS / PHASE SHIFT header field, or apply the corrections
151        * appropriately when performing conversions.
152        */
153    class Rinex3ObsHeader : public Rinex3ObsBase
154    {
155    public:
156 
157          /// A Simple Constructor.
158       Rinex3ObsHeader();
159 
160          /** Clear (empty out) header, setting all data members to
161           * default values */
162       void clear();
163 
164          /// @name RINEX observation file header formatting strings
165          ///@{
166       static const std::string hsVersion;           ///< RINEX VERSION / TYPE
167       static const std::string hsRunBy;             ///< PGM / RUN BY / DATE
168       static const std::string hsComment;           ///< COMMENT
169       static const std::string hsMarkerName;        ///< MARKER NAME
170       static const std::string hsMarkerNumber;      ///< MARKER NUMBER
171       static const std::string hsMarkerType;        ///< MARKER TYPE
172       static const std::string hsObserver;          ///< OBSERVER / AGENCY
173       static const std::string hsReceiver;          ///< REC # / TYPE / VERS
174       static const std::string hsAntennaType;       ///< ANT # / TYPE
175       static const std::string hsAntennaPosition;   ///< APPROX POSITION XYZ
176       static const std::string hsAntennaDeltaHEN;   ///< ANTENNA: DELTA H/E/N
177       static const std::string hsAntennaDeltaXYZ;   ///< ANTENNA: DELTA X/Y/Z
178       static const std::string hsAntennaPhaseCtr;   ///< ANTENNA: PHASECENTER
179       static const std::string hsAntennaBsightXYZ;  ///< ANTENNA: B.SIGHT XYZ
180       static const std::string hsAntennaZeroDirAzi; ///< ANTENNA: ZERODIR AZI
181       static const std::string hsAntennaZeroDirXYZ; ///< ANTENNA: ZERODIR XYZ
182       static const std::string hsCenterOfMass;      ///< CENTER OF MASS: XYZ
183       static const std::string hsNumObs;            ///< # / TYPES OF OBSERV
184       static const std::string hsSystemNumObs;      ///< SYS / # / OBS TYPES
185       static const std::string hsWaveFact;          ///< WAVELENGTH FACT L1/2
186       static const std::string hsSigStrengthUnit;   ///< SIGNAL STRENGTH UNIT
187       static const std::string hsInterval;          ///< INTERVAL
188       static const std::string hsFirstTime;         ///< TIME OF FIRST OBS
189       static const std::string hsLastTime;          ///< TIME OF LAST OBS
190       static const std::string hsReceiverOffset;    ///< RCV CLOCK OFFS APPL
191       static const std::string hsSystemDCBSapplied; ///< SYS / DCBS APPLIED
192       static const std::string hsSystemPCVSapplied; ///< SYS / PCVS APPLIED
193       static const std::string hsSystemScaleFac;    ///< SYS / SCALE FACTOR
194       static const std::string hsSystemPhaseShift;  ///< SYS / PHASE SHIFT
195       static const std::string hsGlonassSlotFreqNo; ///< GLONASS SLOT / FRQ #
196       static const std::string hsGlonassCodPhsBias; ///< GLONASS COD/PHS/BIS
197       static const std::string hsLeapSeconds;       ///< LEAP SECONDS
198       static const std::string hsNumSats;           ///< # OF SATELLITES
199       static const std::string hsPrnObs;            ///< PRN / # OF OBS
200       static const std::string hsEoH;               ///< END OF HEADER
201          ///@}
202 
203          /** Validity bits for the RINEX Observation Header - please
204           * keep ordered as strings above */
205       enum Field
206       {
207          validInvalid = 0,                    ///< Not a valid field
208          validVersion,                        ///< RINEX VERSION / TYPE
209          validFirst = validVersion,           ///< Used fore testing only
210          validRunBy,                          ///< PGM / RUN BY / DATE
211          validComment,                        ///< COMMENT
212          validMarkerName,                     ///< MARKER NAME
213          validMarkerNumber,                   ///< MARKER NUMBER
214          validMarkerType,                     ///< MARKER TYPE
215          validObserver,                       ///< OBSERVER / AGENCY
216          validReceiver,                       ///< REC # / TYPE / VERS
217          validAntennaType,                    ///< ANT # / TYPE
218          validAntennaPosition,                ///< APPROX POSITION XYZ
219          validAntennaDeltaHEN,                ///< ANTENNA: DELTA H/E/N
220          validAntennaDeltaXYZ,                ///< ANTENNA: DELTA X/Y/Z
221          validAntennaPhaseCtr,                ///< ANTENNA: PHASECENTER
222          validAntennaBsightXYZ,               ///< ANTENNA: B.SIGHT XYZ
223          validAntennaZeroDirAzi,              ///< ANTENNA: ZERODIR AZI
224          validAntennaZeroDirXYZ,              ///< ANTENNA: ZERODIR XYZ
225          validCenterOfMass,                   ///< CENTER OF MASS: XYZ
226          validNumObs,                         ///< # / TYPES OF OBSERV
227          validSystemNumObs,                   ///< SYS / # / OBS TYPES
228          validWaveFact,                       ///< WAVELENGTH FACT L1/2
229          validSigStrengthUnit,                ///< SIGNAL STRENGTH UNIT
230          validInterval,                       ///< INTERVAL
231          validFirstTime,                      ///< TIME OF FIRST OBS
232          validLastTime,                       ///< TIME OF LAST OBS
233          validReceiverOffset,                 ///< RCV CLOCK OFFS APPL
234          validSystemDCBSapplied,              ///< SYSTEM DCBS APPLIED
235          validSystemPCVSapplied,              ///< SYSTEM PCVS APPLIED
236          validSystemScaleFac,                 ///< SYSTEM SCALE FACTOR
237          validSystemPhaseShift,               ///< SYS / PHASE SHIFT
238          validGlonassSlotFreqNo,              ///< GLONASS SLOT / FRQ #
239          validGlonassCodPhsBias,              ///< GLONASS COD/PHS/BIS
240          validLeapSeconds,                    ///< LEAP SECONDS
241          validNumSats,                        ///< # OF SATELLITES
242          validPrnObs,                         ///< PRN / # OF OBS
243          validLast                            ///< Used for testing only.
244       };
245 
246          /** RINEX 3 DCBS/PCVS info (for differential code bias and
247           * phase center variations corr.) */
248       class Rinex3CorrInfo
249       {
250       public:
251          std::string satSys;  ///< 1-char SV system (G/R/E/S)
252          std::string name;    ///< program name used to apply corrections
253          std::string source;  ///< source of corrections (URL)
254       };
255 
256          /// RINEX 2 extra "WAVELENGTH FACT" lines
257       class ExtraWaveFact
258       {
259       public:
260             /// List of Sats with this wavelength factor
261          std::vector<SatID> satList;
262             /// vector of wavelength factor values
263          short wavelengthFactor[2];
264             /// Setter method for convenience of python bindings
setWavelengthFactor(short wf1,short wf2)265          ExtraWaveFact& setWavelengthFactor(short wf1, short wf2)
266          {
267             wavelengthFactor[0] = wf1;
268             wavelengthFactor[1] = wf2;
269             return *this;
270          }
271             /** Getter method for convenience of python bindings.
272              * @note I decided to implement two methods instead of a
273              *   single method that took a parameter that required
274              *   sanity check so as to avoid having to do the sanity
275              *   check and exception handling. */
getWavelengthFactor1()276          short getWavelengthFactor1()
277          { return wavelengthFactor[0]; }
278             /// @copydoc getWavelengthFactor1
getWavelengthFactor2()279          short getWavelengthFactor2()
280          { return wavelengthFactor[1]; }
281       };
282 
283          /// Commonly used vector of strings
284       typedef std::vector<std::string> StringVec;
285          /// Simple vector of ints
286       typedef std::vector<int> IntVec;
287          /// Type used to count the number of observations for each observable.
288       typedef std::map<RinexSatID, IntVec> PRNNumObsMap;
289          /** Scale Factor corrections for observations
290           * map <ObsType, ScaleFactor> */
291       typedef std::map<RinexObsID, int> ScaleFacMap;
292          /** Per-system scale factor corrections.
293           * Satellite system map of scale factor maps
294           * <(G/R/E/S), <Rinex3ObsType, scalefactor>> */
295       typedef std::map<std::string, ScaleFacMap> SysScaleFacMap;
296          /// Vector of obervables
297       typedef std::vector<RinexObsID> RinexObsVec;
298          /** Map system to observables
299           * map <sys char, vec<ObsID> >;
300           * NB defines data vec in ObsData */
301       typedef std::map<std::string, RinexObsVec> RinexObsMap;
302          /// @todo document me
303       typedef std::map<std::string, RinexObsID> ObsIDMap;
304          /// @todo document me
305       typedef std::map<std::string, ObsIDMap> VersionObsMap;
306          /// Map satellite ID to phase shift
307       typedef std::map<RinexSatID, double> SVPhsShftMap;
308          /// Map observation type to sv-phase shift map
309       typedef std::map<RinexObsID, SVPhsShftMap> ObsPhsShftMap;
310          /// Map system to observation type phase shift map
311       typedef std::map<std::string, ObsPhsShftMap> SysPhsShftMap;
312          /// Map GLONASS SV ID to frequency number
313       typedef std::map<RinexSatID, int> GLOFreqNumMap;
314          /// Map GLONASS SV observable to code phase bias
315       typedef std::map<RinexObsID, double> GLOCodPhsBias;
316          /// Map SysChar + R2 Obs Type to Obs ID
317       typedef std::map<std::string,std::string> DisAmbMap;
318          /// Corrections (e.g. code bias) vector
319       typedef std::vector<Rinex3CorrInfo> CorrVec;
320          /// Vector of wavelength factors
321       typedef std::vector<ExtraWaveFact> FactorVector;
322       typedef std::set<Field> FieldSet;
323 
324       class Fields
325       {
326       public:
327          Fields() = default;
Fields(const FieldSet & fields)328          Fields(const FieldSet& fields)
329                : fieldsSet(fields)
330          {}
331             /// Compare field sets.
operator ==(const Fields & rhs) const332          bool operator==(const Fields& rhs) const
333          { return fieldsSet == rhs.fieldsSet; }
334             /// Return true if the set of fields differs between this and rhs.
operator !=(const Fields & rhs) const335          bool operator!=(const Fields& rhs) const
336          { return !(fieldsSet == rhs.fieldsSet); }
337             /// Set a specific field.
set(Field f)338          Fields& set(Field f)
339          { fieldsSet.insert(f); return *this; }
340             /// Clear a specific field.
clear(Field f)341          Fields& clear(Field f)
342          { fieldsSet.erase(f); return *this; }
343             /// Return true if the specific field is set (preferred to operator&).
isSet(Field f) const344          bool isSet(Field f) const
345          { return fieldsSet.count(f) > 0; }
346             /// Clear all set fields.
clear()347          void clear()
348          { fieldsSet.clear(); }
349             /// Return true if fieldsSet is empty, false otherwise.
empty() const350          bool empty() const
351          { return fieldsSet.empty(); }
352             /** Backwards compatibility method for code still implemented
353              * around bit flags.
354              */
355          Fields operator&(const Fields& rhs) const;
356             /** Backwards compatibility method for code still implemented
357              * around bit flags.
358              */
359          Fields operator|(const Fields& rhs) const;
360             /** Backwards compatibility method for code still implemented
361              * around bit flags.
362              * @deprecated Please use isSet() instead. */
363          Field operator&(Field rhs) const;
364             /** Alias for set() for backwards compatibility.
365              * @deprecated Please use set() instead. */
operator |=(Field rhs)366          Fields& operator|=(Field rhs)
367          { return set(rhs); }
368             /** Alias for clear(Field)
369              * @deprecated Please use clear(Field) instead. */
operator ^=(Field rhs)370          Fields& operator^=(Field rhs)
371          { return clear(rhs); }
372             /** Determine if a header is valid.
373              * @note This object is assumed to be a set of required
374              *   fields.  Generally you would call this method on one of
375              *   the allValid2, etc. static objects defined above.
376              * @see isValid(double,const Fields&)
377              * @code{.cpp}
378              * if (Fields::allValid2.isValid(flags))
379              * @endcode
380              * @param[in] present The set of flags present in an existing
381              *   header to be compared with this set of required flags.
382              * @return true If all the fields in fieldsSet are also
383              *   contained in present.fieldsSet.
384              */
385          bool isValid(const Fields& present) const;
386             /** Determine if a header is valid.
387              * @param[in] version The RINEX version being validated.
388              * @param[in] present The set of flags present in an existing
389              *   header to be compared with this set of required flags.
390              * @return true If all the fields in the fieldsSet value
391              *   appropriate for the specified version are also contained
392              *   in present.fieldsSet.
393              */
isValid(double version,const Fields & present)394          static bool isValid(double version, const Fields& present)
395          { return getRequired(version).isValid(present); }
396             /** Add descriptive information to an exception about which
397              * header fields are missing.  This object is assumed to be
398              * the set of header fields that are expected.
399              * @param[in] valid The set of present header fields.
400              * @param[out] exc The exception to add descriptive text to.
401              * @post exc will have text entries added to it for each of
402              *   the missing header fields, i.e. each field set in
403              *   allValid that is not set in valid.
404              */
405          void describeMissing(const Fields& valid, Exception& exc);
406             /** Get a reference to the set of required header fields for
407              * a given RINEX version. */
408          static Fields getRequired(double version);
409 
410             /// All the header fields set in this object.
411          FieldSet fieldsSet;
412       };
413 
414       static const Fields allValid2, allValid30, allValid301, allValid302,
415          allValid303;
416 
417          /** Storage for R2 <-> R3 conversion of obstypes during
418           * reallyGet/Put Vector of strings containing ver 2 obs types
419           * (e.g. "C1" "L2") defined in reallyGet; also defined in
420           * PrepareVer2Write() from R3 ObsIDs */
421       StringVec R2ObsTypes;
422 
423          /** map between RINEX ver 3 ObsIDs and ver 2 obstypes for
424           * each system: reallyPut */
425       VersionObsMap mapSysR2toR3ObsID;
426 
427          /** map Sys + R2ot to their ObsID origins*/
428       DisAmbMap R2DisambiguityMap;
429 
430 
431       double version;                  ///< RINEX 3 version/type
432       std::string fileType;            ///< RINEX 3 file type
433          /// file sys char: RinexSatID system OR Mixed
434       std::string fileSys;
435          /** If false, the file type and system will be re-generated
436           * in the gpstk preferred format when writing the header,
437           * otherwise the strings fileType fileSys will be written
438           * unaltered */
439       bool preserveVerType;
440       SatID fileSysSat;                ///< fileSys as a SatID
441       std::string fileProgram;         ///< program used to generate file
442       std::string fileAgency;          ///< who ran program
443       std::string date;                ///< when program was run
444          /** If false, the current system time will be used when
445           * writing the header, otherwise the value in date will be
446           * used. */
447       bool preserveDate;
448       StringVec commentList;           ///< comments in header
449       std::string markerName;          ///< MARKER NAME
450       std::string markerNumber;        ///< MARKER NUMBER
451       std::string markerType;          ///< MARKER TYPE
452       std::string observer;            ///< who collected the data
453       std::string agency;              ///< observer's agency
454       std::string recNo;               ///< receiver number
455       std::string recType;             ///< receiver type
456       std::string recVers;             ///< receiver version
457       std::string antNo;               ///< antenna number
458       std::string antType;             ///< antenna type
459       gpstk::Triple antennaPosition;   ///< APPROX POSITION XYZ
460       gpstk::Triple antennaDeltaHEN;   ///< ANTENNA: DELTA H/E/N
461       gpstk::Triple antennaDeltaXYZ;   ///< ANTENNA: DELTA X/Y/Z
462       std::string antennaSatSys;       ///< ANTENNA P.CTR BLOCK: SAT SYS
463       std::string antennaObsCode;      ///< ANTENNA P.CTR BLOCK: OBS CODE
464       gpstk::Triple antennaPhaseCtr;   ///< ANTENNA P.CTR BLOCK: PCTR POS
465       gpstk::Triple antennaBsightXYZ;  ///< ANTENNA B.SIGHT XYZ
466       double        antennaZeroDirAzi; ///< ANTENNA ZERODIR AZI
467       gpstk::Triple antennaZeroDirXYZ; ///< ANTENNA ZERODIR XYZ
468       gpstk::Triple centerOfMass;      ///< vehicle CENTER OF MASS: XYZ
469       RinexObsMap mapObsTypes;         ///< SYS / # / OBS TYPES
470       short wavelengthFactor[2];       ///< WAVELENGTH FACT (system-wide)
471       FactorVector extraWaveFactList;  ///< WAVELENGTH FACT (per SV)
472       std::string sigStrengthUnit;     ///< SIGNAL STRENGTH UNIT
473       double interval;                 ///< INTERVAL
474       CivilTime firstObs;              ///< TIME OF FIRST OBS
475       CivilTime lastObs;               ///< TIME OF LAST OBS
476       int receiverOffset;              ///< RCV CLOCK OFFS APPL
477       CorrVec infoDCBS;                ///< DCBS INFO
478       CorrVec infoPCVS;                ///< PCVS INFO
479       SysScaleFacMap sysSfacMap;       ///< SYS / SCALE FACTOR
480       SysPhsShftMap sysPhaseShift;     ///< SYS / PHASE SHIFT
481       GLOFreqNumMap glonassFreqNo;     ///< GLONASS SLOT / FRQ #
482       GLOCodPhsBias glonassCodPhsBias; ///< GLONASS COD/PHS/BIS
483       int leapSeconds;                 ///< LEAP SECONDS
484       short numSVs;                    ///< # OF SATELLITES
485       PRNNumObsMap numObsForSat;       ///< PRN / # OF OBS
486 
487 
488          /// number & types of observations R2 only
489          ///@bug  this is being used but is not actually being filled
490       RinexObsVec obsTypeList;
491 
492          /// bits set when header rec.s present & valid
493       Fields valid;
494          /// true if found END OF HEADER
495       bool validEoH;
496          /// Map P to Y code observations in RINEX 2 files
497       bool PisY;
498 
499          /// Used to help debug this class
500       static int debug;
501 
502          /// Destructor
~Rinex3ObsHeader()503       virtual ~Rinex3ObsHeader()
504       {}
505 
506          // The next four lines comprise our common interface.
507 
508          /// Rinex3ObsHeader is a "header" so this function always
509          /// returns true.
isHeader() const510       virtual bool isHeader() const
511       { return true; }
512 
513          /** This is a debug output function which provides a lot of
514           * detail about the header contents, based on the value of \a
515           * version (RINEX format version).
516           */
dump(std::ostream & s) const517       virtual void dump(std::ostream& s) const
518       { dump(s, version); }
519 
520          /** This is a debug output function which provides a lot of
521           * detail about the header contents for a specified RINEX
522           * format version.
523           * @param[in] dumpVersion The RINEX format version to use
524           *   when dumping the contents of this header.  Potentially
525           *   affects the representation of obs IDs, as well as which
526           *   header fields are printed.
527           */
528       void dump(std::ostream& s, double dumpVersion) const;
529 
530          /** This method returns the numerical index of a given observation
531           *
532           * @param[in] type String representing the observation type.
533           * @throw InvalidRequest
534           */
535       virtual std::size_t getObsIndex(const std::string& type ) const;
536 
537          /** This method returns the numerical index of a given observation
538           *
539           * @param[in] sys   GNSS system character for the obs
540           * @param[in] obsID RinexObsID of the observation
541           * @throw InvalidRequest
542           */
543       virtual std::size_t getObsIndex(const std::string& sys,
544                                       const RinexObsID& obsID ) const;
545 
546          /** Parse a single header record, and modify valid
547           * accordingly.  Used by reallyGetRecord for both
548           * Rinex3ObsHeader and Rinex3ObsData.
549           * @throw FFStreamError
550           */
551       void parseHeaderRecord(std::string& line);
552 
553          /** Compute number of valid header records that
554           * writeHeaderRecords() will write */
555       int numberHeaderRecordsToBeWritten(void) const throw();
556 
557          /** Write all valid header records to the given stream.  Used
558           * by reallyPutRecord for both Rinex3ObsHeader and
559           * Rinex3ObsData.
560           * @throw FFStreamError
561           * @throw StringUtils::StringException
562           */
563       void writeHeaderRecords(FFStream& s) const;
564 
565          /// Return boolean : is this a valid Rinex header?
isValid() const566       bool isValid() const
567       { return (validEoH && Fields::isValid(version, valid)); }
568 
569          /** Compute map of obs types for use in writing version 2
570           * header and data */
571       void prepareVer2Write(void);
572 
573          /** Compare this header with another.
574           * @param[in] right the header to compare this with.
575           * @param[out] diffs The header strings/identifiers that are
576           *   different between this and right.
577           * @param[in] inclExclList a list of header strings to be ignored
578           *   or used when making the comparison (e.g. "RINEX VERSION / TYPE").
579           * @param[in] incl When true, only header lines listed in
580           *   inclExclList will be compared.  When false, differences in
581           *   header lines in inclExclList will be ignored.
582           * @return true if this and right match given the
583           *   included/excluded headers. */
584       bool compare(const Rinex3ObsHeader& right,
585                    StringVec& diffs,
586                    const StringVec& inclExclList,
587                    bool incl = false);
588 
589          /// Return the RINEX header label for the given field enumeration.
590       static std::string asString(Field b);
591          /// Convert a RINEX header field label string into its matching enum.
592       static Field asField(const std::string& s);
593 
594          /// Setter method for convenience of python bindings
setWavelengthFactor(short wf1,short wf2)595       Rinex3ObsHeader& setWavelengthFactor(short wf1, short wf2)
596       {
597          wavelengthFactor[0] = wf1;
598          wavelengthFactor[1] = wf2;
599          return *this;
600       }
601          /// @copydoc ExtraWaveFact::getWavelengthFactor1()
getWavelengthFactor1()602       short getWavelengthFactor1()
603       { return wavelengthFactor[0]; }
604          /// @copydoc ExtraWaveFact::getWavelengthFactor1()
getWavelengthFactor2()605       short getWavelengthFactor2()
606       { return wavelengthFactor[1]; }
607 
608    protected:
609 
610 
611          /** outputs this record to the stream correctly formatted.
612           * @throw std::exception
613           * @throw FFStreamError
614           * @throw StringUtils::StringException
615           */
616       virtual void reallyPutRecord(FFStream& s) const;
617 
618          /** This function retrieves the RINEX Header from the given FFStream.
619           * If an stream error is encountered, the stream is reset to its
620           *  original position and its fail-bit is set.
621           * @throw std::exception
622           * @throw StringException when a StringUtils function fails
623           * @throw FFStreamError when exceptions(failbit) is set and
624           *  a read or formatting error occurs.  This also resets the
625           *  stream to its pre-read position. */
626       virtual void reallyGetRecord(FFStream& s);
627 
628 
629          /** Helper methods
630           * The conversion between RINEX v2.11 to RINEX v3 observation
631           * type is fraught with system-specific idiosyncracies.   These
632           * methods read the list of v2.11 obs types stored in R2ObsTypes
633           * and attempt to build a corresponding list of v3 observation
634           * types where appropriate.
635           * @throw FFStreamError */
636       std::vector<RinexObsID> mapR2ObsToR3Obs_G();
637       std::vector<RinexObsID> mapR2ObsToR3Obs_R();
638       std::vector<RinexObsID> mapR2ObsToR3Obs_E();
639       std::vector<RinexObsID> mapR2ObsToR3Obs_S();
640 
641          /** Because of how pseudo-observables are handled, we need
642           * this function to remap the contents of mapObsTypes such
643           * that ionospheric delay and channel pseudo-observables get
644           * the treatment they need. */
645       void remapObsTypes(RinexObsMap& remapped,
646                          std::map<std::string,unsigned>& obsCount)
647          const;
648 
649       friend class Rinex3ObsData;
650 
651 
652    private:
653 
654          /** Converts the daytime \a dt into a Rinex Obs time
655           * string for the header */
656       std::string writeTime(const CivilTime& civtime) const;
657 
658          /** This function sets the time for this header.
659           * It looks at \a line to obtain the needed information. */
660       CivilTime parseTime(const std::string& line) const;
661 
662          /// save ObsID for cont. "PHASE SHIFT" R3.01
663       RinexObsID sysPhaseShiftObsID;
664          /// save the syschar while reading ScaleFactor
665       std::string satSysTemp;
666          /// recall the prev sat. sys for continuation lines.
667       std::string satSysPrev;
668          /// save OBS # / TYPES and Sys / SCALE FACTOR for continuation lines.
669       int numObs;
670          /// recall the prev # obs for cont. lines
671       int numObsPrev;
672          /// save PRN while reading PRN/OBS cont. lines
673       RinexSatID lastPRN;
674          /// Scale factor holding data for continuation lines.
675       int factor, factorPrev;
676 
677    }; // end class Rinex3ObsHeader
678 
679    std::ostream& operator<<(std::ostream& s, const Rinex3ObsHeader::Fields& v);
680 
681       //@}
682 
683 } // namespace
684 
685 #endif // GPSTK_RINEX3OBSHEADER_HPP
686