00001 #pragma ident "$Id: IonexStore.cpp 3044 2012-04-04 10:50:58Z coandrei $"
00002
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "IonexStore.hpp"
00034
00035 using namespace gpstk::StringUtils;
00036 using namespace gpstk;
00037 using namespace std;
00038
00039 namespace gpstk
00040 {
00041
00042
00043
00044 static const double C2_FACT = 40.3e+16;
00045
00046
00047
00048 void IonexStore::loadFile( const std::string& filename )
00049 throw(FileMissingException)
00050 {
00051
00052 try
00053 {
00054
00055
00056 IonexStream strm(filename.c_str(), std::ios::in);
00057
00058 if (!strm)
00059 {
00060
00061 FileMissingException e( "File " + filename +
00062 " could not be opened.");
00063 GPSTK_THROW(e);
00064
00065 }
00066
00067
00068 IonexHeader header;
00069 strm >> header;
00070
00071 if ( !header.valid )
00072 {
00073
00074 FileMissingException e( "File " + filename +
00075 " could not be opened. Check again " +
00076 "the path or the name provided!");
00077 GPSTK_THROW(e);
00078
00079 }
00080
00081
00082 addFile(filename,header);
00083
00084
00085 inxDCBMap[header.firstEpoch] = header.svsmap;
00086
00087
00088 IonexData iod;
00089 while ( strm >> iod && iod.isValid() )
00090 {
00091 addMap(iod);
00092 }
00093
00094 }
00095 catch (gpstk::Exception& e)
00096 {
00097 GPSTK_RETHROW(e);
00098 }
00099
00100 }
00101
00102
00103
00104
00105 void IonexStore::addMap(const IonexData& iod)
00106 throw()
00107 {
00108
00109 DayTime t(iod.time);
00110 IonexData::IonexValType type(iod.type);
00111
00112 if (type != IonexData::UN)
00113 {
00114 inxMaps[t][type] = iod;
00115 }
00116
00117 if (t < initialTime)
00118 {
00119 initialTime = t;
00120 }
00121 else if (t > finalTime)
00122 {
00123 finalTime = t;
00124 }
00125
00126 }
00127
00128
00129
00138 void IonexStore::dump( std::ostream& s,
00139 short detail ) const
00140 throw()
00141 {
00142
00143 s << "IonexStore dump() function" << std::endl;
00144
00145 std::vector<std::string> fileNames = getFileNames();
00146 std::vector<std::string>::const_iterator f;
00147
00148 for (f = fileNames.begin(); f != fileNames.end(); f++)
00149 {
00150 s << *f << std::endl;
00151 }
00152
00153 s << std::endl;
00154
00155
00156 if (detail >= 0)
00157 {
00158
00159 s << "Data stored for: " << std::endl;
00160 s << " # " << fileNames.size() << " files." << std::endl;
00161 s << " # " << inxMaps.size() << " epochs" << std::endl;
00162 s << " # " << "over time span "<< getInitialTime()
00163 << " to " << getFinalTime() << "." << std::endl;
00164
00165 s << std::endl;
00166
00167 if (detail == 0)
00168 {
00169 return;
00170 }
00171
00172 s << "--------------------" << std::endl;
00173 s << "EPOCH"
00174 << std::setw(21) << "TEC"
00175 << std::setw(5) << "RMS"<< std::endl;
00176 s << "--------------------" << std::endl;
00177
00178 int ntec(0), nrms(0);
00179
00180 IonexMap::const_iterator it;
00181
00182 for (it=inxMaps.begin(); it != inxMaps.end(); it++)
00183 {
00184
00185 s << it->first << " ";
00186
00187 if ( it->second.count(IonexData::TEC) )
00188 {
00189 ntec++;
00190 s << " YES ";
00191 }
00192 else
00193 {
00194 s << " ";
00195 }
00196
00197 if ( it->second.count(IonexData::RMS) )
00198 {
00199 nrms++;
00200 s << " YES ";
00201 }
00202 else
00203 {
00204 s << " ";
00205 }
00206
00207 s << std::endl;
00208
00209 }
00210
00211
00212 s << "--------------------" << std::endl;
00213 s << "Total epochs: "
00214 << std::setw(5) << ntec
00215 << std::setw(5) << nrms << std::endl;
00216 s << "--------------------" << std::endl;
00217
00218 }
00219
00220
00221 return;
00222
00223
00224 }
00225
00226
00227
00228
00229 void IonexStore::clear()
00230 throw()
00231 {
00232
00233 inxMaps.clear();
00234
00235 initialTime = DayTime::END_OF_TIME;
00236 finalTime = DayTime::BEGINNING_OF_TIME;
00237
00238 return;
00239
00240 }
00241
00242
00243
00266 Triple IonexStore::getIonexValue( const DayTime& t,
00267 const Position& RX,
00268 int strategy ) const
00269 throw(InvalidRequest)
00270 {
00271
00272
00273
00274 Triple tecval(0.0,0.0,0.0);
00275
00276
00277 if (t < getInitialTime())
00278 {
00279 InvalidRequest e("Inadequate data before requested time");
00280 GPSTK_THROW(e);
00281 }
00282
00283 if (t > getFinalTime() )
00284 {
00285 InvalidRequest e("Inadequate data after requested time");
00286 GPSTK_THROW(e);
00287 }
00288
00289
00290 Position pos(RX);
00291 if ( pos.getSystemName() != "Geocentric" )
00292 {
00293
00294 InvalidRequest e("Position object is not in GEOCENTRIC coordinates");
00295
00296 GPSTK_THROW(e);
00297
00298 }
00299
00300
00301 int nmap;
00302 if (strategy == 1) nmap = 1;
00303 else if (strategy == 2) nmap = 2;
00304 else if (strategy == 3) nmap = 2;
00305 else if (strategy == 4) nmap = 1;
00306 else
00307 {
00308 InvalidRequest e("Invalid interpolation stategy");
00309 GPSTK_THROW(e);
00310 }
00311
00312
00313 DayTime T[2];
00314
00315 IonexMap::const_iterator itm = inxMaps.find(t);
00316 try
00317 {
00318
00319 if( itm != inxMaps.end() )
00320 {
00321
00322
00323 itm = inxMaps.lower_bound(t);
00324
00325 T[0] = itm->first;
00326 T[1] = (++itm)->first;
00327
00328 }
00329 else
00330 {
00331
00332
00333 itm = inxMaps.lower_bound(t);
00334
00335 T[1] = itm->first;
00336 T[0] = (--itm)->first;
00337
00338 }
00339
00340 }
00341 catch (...)
00342 {
00343 InvalidRequest e("IonexStore::getIonexValue() ... Invalid time!");
00344 GPSTK_THROW(e);
00345 }
00346
00347
00348
00349 double f[2];
00350 f[0] = (T[1]-t ) / (T[1]-T[0]);
00351 f[1] = (t -T[0]) / (T[1]-T[0]);
00352
00353
00354 if( nmap == 1 )
00355 {
00356
00357
00358 if( f[1] > f[0] )
00359 {
00360 T[0] = T[1];
00361 }
00362
00363
00364 f[0] = 1.0;
00365
00366 }
00367
00368
00369 for(int imap = 0; imap < nmap; imap++)
00370 {
00371
00372
00373
00374 Position pos;
00375 if (strategy == 1 || strategy == 2)
00376 {
00377
00378 pos = RX;
00379
00380 }
00381 else
00382 {
00383
00384
00385 double sec2deg( 4.16666666666667e-3 );
00386
00387
00388 pos = RX;
00389 pos.theArray[1] = pos.theArray[1] + ( t - T[imap] ) * sec2deg;
00390
00391 }
00392
00393
00394
00395 itm = inxMaps.find(T[imap]);
00396
00397
00398 IonexValTypeMap ivtm = (*itm).second;
00399
00400
00401 IonexData iod;
00402
00403
00404 if ( ivtm.find(IonexData::TEC) != ivtm.end() )
00405 {
00406
00407 iod = ivtm[IonexData::TEC];
00408 tecval[0] = tecval[0] + f[imap]*iod.getValue(pos);
00409
00410 }
00411
00412
00413 if ( ivtm.find(IonexData::RMS) != ivtm.end() )
00414 {
00415
00416 iod = ivtm[IonexData::RMS];
00417 tecval[1] = tecval[1] + f[imap]*iod.getValue(pos);
00418
00419 }
00420
00421 }
00422
00423
00424
00425 tecval[2] = RX.theArray[2];
00426
00427 return tecval;
00428
00429 }
00430
00431
00432
00445 double IonexStore::getSTEC( const double& elevation,
00446 const double& tecval,
00447 const std::string& ionoMapType ) const
00448 throw (InvalidParameter)
00449 {
00450
00451 if (tecval < 0)
00452 {
00453 InvalidParameter e("Invalid TEC parameter.");
00454 GPSTK_THROW(e);
00455 }
00456
00457 if( ionoMapType != "NONE" && ionoMapType != "SLM" &&
00458 ionoMapType != "MSLM" && ionoMapType != "ESM" )
00459 {
00460 InvalidParameter e("Invalid ionosphere mapping function.");
00461 GPSTK_THROW(e);
00462 }
00463
00464 if (elevation < 0.0)
00465 {
00466
00467 return 0.0;
00468
00469 }
00470 else
00471 {
00472
00473 return ( tecval * iono_mapping_function(elevation, ionoMapType) );
00474
00475 }
00476
00477 }
00478
00479
00480
00491 double IonexStore::getIono( const double& elevation,
00492 const double& tecval,
00493 const double& freq,
00494 const std::string& ionoMapType ) const
00495 throw (InvalidParameter)
00496 {
00497
00498 if (tecval < 0)
00499 {
00500 InvalidParameter e("Invalid TEC parameter.");
00501 GPSTK_THROW(e);
00502 }
00503
00504 if( ionoMapType != "NONE" && ionoMapType != "SLM" &&
00505 ionoMapType != "MSLM" && ionoMapType != "ESM" )
00506 {
00507 InvalidParameter e("Invalid ionosphere mapping function.");
00508 GPSTK_THROW(e);
00509 }
00510
00511 if (elevation < 0.0)
00512 {
00513
00514 return 0.0;
00515
00516 }
00517 else
00518 {
00519
00520 return ( C2_FACT / (freq * freq) * tecval
00521 * iono_mapping_function(elevation, ionoMapType) );
00522
00523 }
00524
00525 }
00526
00527
00528
00543 double IonexStore::iono_mapping_function( const double& elevation,
00544 const std::string& ionoMapType ) const
00545 {
00546
00547
00548 double map(1.0);
00549
00550 double Re = 6371.0;
00551
00552 double z0 = 90.0 - elevation;
00553
00554 if( ionoMapType == "SLM" )
00555 {
00556
00557
00558
00559
00560
00561 double ionoHeight = 450.0;
00562
00563 double sinzipp = Re / (Re + ionoHeight) * std::sin(z0*DEG_TO_RAD);
00564 double zipprad = std::asin(sinzipp);
00565
00566 map = 1.0/std::cos(zipprad);
00567
00568 }
00569 else if( ionoMapType == "MSLM" )
00570 {
00571
00572 if( z0 <= 80.0 )
00573 {
00574
00575 double ionoHeight = 506.7;
00576 double alfa = 0.9782;
00577
00578 double sinzipp = Re / (Re + ionoHeight)
00579 * std::sin(alfa * z0 * DEG_TO_RAD);
00580 double zipprad = std::asin(sinzipp);
00581
00582 map = 1.0/std::cos(zipprad);
00583 }
00584
00585 }
00586 else if( ionoMapType == "ESM" )
00587 {
00588
00589 }
00590 else
00591 {
00592
00593 }
00594
00595
00596 return map;
00597
00598 }
00599
00600
00601
00611 double IonexStore::findDCB( const SatID sat,
00612 const DayTime& time ) const
00613 throw(InvalidRequest)
00614 {
00615
00616
00617 if ( time < getInitialTime() )
00618 {
00619 InvalidRequest e("Inadequate data before requested time");
00620 GPSTK_THROW(e);
00621 }
00622
00623 if ( time > getFinalTime() )
00624 {
00625 InvalidRequest e("Inadequate data after requested time");
00626 GPSTK_THROW(e);
00627 }
00628
00629 double dt(0.0);
00630 IonexDCBMap::const_iterator itm = inxDCBMap.begin();
00631
00632
00633 while ( itm != inxDCBMap.end() )
00634 {
00635
00636
00637 dt = time - itm->first;
00638
00639
00640 if( dt < 0.0 )
00641 {
00642
00643 InvalidRequest e( "Inadequate data after requested time: " +
00644 time.asString() );
00645 GPSTK_THROW(e);
00646
00647 }
00648 else
00649 {
00650
00651 if( dt < 86400.0 )
00652 {
00653
00654 IonexHeader::SatDCBMap satdcb( itm->second );
00655 IonexHeader::SatDCBMap::const_iterator iprn( satdcb.find(sat) );
00656
00657
00658 if ( iprn == satdcb.end() )
00659 {
00660
00661 InvalidRequest e( "There is no DCB value for satellite " +
00662 asString(sat) );
00663 GPSTK_THROW(e);
00664
00665 }
00666 else
00667 {
00668
00669 return iprn->second.bias;
00670
00671 }
00672
00673 }
00674 else
00675 {
00676
00677 itm++;
00678
00679 }
00680
00681 }
00682
00683 }
00684
00685
00686
00687 return 0.0;
00688
00689 }
00690
00691
00692 }