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 IonexData.hpp
41  * Encapsulate IONEX file data, including I/O
42  */
43 
44 #ifndef GPSTK_IONEXDATA_HPP
45 #define GPSTK_IONEXDATA_HPP
46 
47 #include <map>
48 
49 #include "FFStream.hpp"
50 #include "Position.hpp"
51 #include "Vector.hpp"
52 #include "WGS84Ellipsoid.hpp"
53 
54 #include "IonexStream.hpp"
55 
56 
57 
58 namespace gpstk
59 {
60 
61       /// @ingroup IonosphereMaps
62       //@{
63 
64       /** This class models a IONEX Data Record.
65        *
66        * @sa gpstk::IonexStream and gpstk::IonexHeader
67        * @sa main ionex test.cpp for example
68        */
69    class IonexData : public IonexBase
70    {
71    public:
72 
73 
74          /**
75           * @name IonexDataFormatStrings
76           * IONEX Data Formatting Strings
77           */
78          //@{
79       static const std::string startTecMapString;     ///<"START OF TEC MAP"
80       static const std::string startRmsMapString;     ///<"START OF RMS MAP"
81       static const std::string startHgtMapString;     ///<"START OF HEIGHT MAP"
82       static const std::string currentEpochString;    ///<"EPOCH OF CURRENT MAP"
83       static const std::string dataBlockString;       ///<"LAT/LON1/LON2/DLON/H"
84       static const std::string endTecMapString;       ///<"END OF TEC MAP"
85       static const std::string endRmsMapString;       ///<"END OF RMS MAP"
86       static const std::string endHgtMapString;       ///<"END OF HEIGHT MAP"
87       static const std::string endOfFile;             ///<"END OF FILE"
88          //@}
89 
90 
91          /// A structure used to store IONEX Value Types
92       struct IonexValType
93       {
94 
95          std::string type;          ///< type e.g. TEC, RMS
96          std::string description;   ///< Description (optional)
97          std::string units;         ///< units (optional). E.g. "meters"
98 
IonexValTypegpstk::IonexData::IonexValType99          IonexValType()
100             : type( std::string("UN") ),
101               description( std::string("Unknown or Invalid") ),
102               units( std::string("") )
103          {};
104 
IonexValTypegpstk::IonexData::IonexValType105          IonexValType(std::string t, std::string d, std::string u)
106             : type(t), description(d), units(u) {};
107 
108       }; // End of struct 'IonexValType'
109 
110 
111          /**
112           * @name Standard IONEX value types
113           */
114          //@{
115       static const IonexValType UN;
116       static const IonexValType TEC;
117       static const IonexValType RMS;
118          //@}
119 
120 
121          /**
122           * @name IonexDataValues
123           */
124          //@{
125       int mapID;     ///< denote the internal number of the current map
126       int dim[3];    ///< How many values are along latitude, longitude, height
127       CommonTime time;  ///< the time corresponding to the current data records
128 
129       IonexValType type;      ///< Type of data either TEC or RMS
130       Vector<double> data;    ///< TEC or RMS data
131 
132          // The following fields are similar to the ones in 'IonexHeader'
133       int exponent;           ///< Exponent defining the unit of the values
134 
135       double lat[3];          ///< Definition of a grid in latitude
136       double lon[3];          ///< Definition of a grid in longitude
137       double hgt[3];          ///< Definition of a grid in height
138 
139       bool valid;             ///< Validity flag
140          //@}
141 
142 
143          /// Default constructor.
IonexData()144       IonexData()
145          : time(CommonTime::BEGINNING_OF_TIME), valid(false) {};
146 
147 
148          /// Destructor
~IonexData()149       virtual ~IonexData() {};
150 
151 
152 
153          // The next four lines define our common interface
154 
155          /// IonexData is a "data", so this function always returns true
isData() const156       virtual bool isData() const
157       { return true; }
158 
159 
160          /// Am I an valid object?
isValid() const161       virtual bool isValid() const
162       { return valid; };
163 
164 
165          /// A debug output function.
166       virtual void dump (std::ostream& s = std::cout) const;
167 
168 
169          /** Get the position of a grid point based on input position
170           *
171           * @param in     input lat, lon and height (Triple object)
172           * @param type   grid point to be returned
173           *               (1) neareast grid point
174           *               (2) lower left hand grid point
175           * @param out    output lat, lon and height (Triple object)
176           * @return       the index within the data
177           * @throw InvalidRequest
178           * @warning Keep in mind the assumptions of IONEX grid (i.e., latitude
179           *          between [87.5, -87.5], longitude between [-180, 180])
180           *          when you construct a Triple object.
181           */
182       int getIndex( const Triple& in, const int& type, Triple& out ) const;
183 
184 
185          /** Get IONEX TEC or RMS value as a function of the position
186           *  and nominal height.
187           *
188           * A simple 4-point formula is applied to interpolate between
189           * grid points.
190           *
191           * For more information see page 3 of IONEX manual:
192           *
193           * http://igscb.jpl.nasa.gov/igscb/data/format/ionex1.pdf
194           *
195           * @param pos             input position (Position object).
196           *
197           * @return                Computed TEC or RMS value.
198           * @throw InvalidRequest
199           * @throw FFStreamError
200           */
201       double getValue(const Position& pos) const;
202 
203 
204    protected:
205 
206          /** Writes a correctly formatted record from this data to stream \a s.
207           *
208           * @throw std::exception
209           * @throw FFStreamError
210           * @throw StringException when a StringUtils function fails
211           */
212       virtual void reallyPutRecord(FFStream& s) const;
213 
214 
215          /** This function obtains a IONEX Data record from
216           *  the given FFStream.
217           *
218           * If there is an error reading the stream, it is reset
219           * to its original position and its fail-bit is set.
220           *
221           * @throw std::exception
222           * @throw StringException when a StringUtils function fails
223           * @throw FFStreamError when exceptions(failbit) is set and
224           *   a read or formatting error occurs.  This also resets the
225           *   stream to its pre-read position.
226           */
227       virtual void reallyGetRecord(FFStream& s);
228 
229 
230    private:
231 
232 
233          /** Writes the CommonTime object into IONEX format. If it's a bad time,
234           * it will return blanks.
235           *
236           * @param dt    time to be written into a IONEX data record.
237           * @throw StringUtils::StringException
238           */
239       std::string writeTime(const CommonTime& dt) const;
240 
241 
242          /** This function constructs a CommonTime object from the given
243           *  parameters.
244           *
245           * @param line    Encoded time string found in the IONEX record.
246           */
247       CommonTime parseTime(const std::string& line) const;
248 
249 
250    }; // End of class 'IonexData'
251 
252 
253       /// operator == for IonexData::IonexValType
operator ==(const IonexData::IonexValType & x,const IonexData::IonexValType & y)254    inline bool operator==( const IonexData::IonexValType& x,
255                            const IonexData::IonexValType& y )
256    {return (x.type == y.type); };
257 
258 
259       /// operator != for IonexData::IonexValType
operator !=(const IonexData::IonexValType & x,const IonexData::IonexValType & y)260    inline bool operator!=( const IonexData::IonexValType& x,
261                            const IonexData::IonexValType& y )
262    {return (x.type != y.type); };
263 
264 
265       /// operator < for IonexData::IonexValType
operator <(const IonexData::IonexValType & x,const IonexData::IonexValType & y)266    inline bool operator<( const IonexData::IonexValType& x,
267                           const IonexData::IonexValType& y )
268    {return (x.type < y.type); };
269 
270 
271       /// operator << for IonexData::IonexValType
operator <<(std::ostream & s,const IonexData::IonexValType ivt)272    inline std::ostream& operator<<( std::ostream& s,
273                                     const IonexData::IonexValType ivt )
274    {
275       return s << "Type= " << ivt.type
276                << ", Description= " << ivt.description
277                << ", Units= " << ivt.units;
278    };
279 
280 
281       //@}
282 
283 
284 }  // End of namespace gpstk
285 #endif   // GPSTK_IONEXDATA_HPP
286