SMODFData.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: SMODFData.cpp 1122 2008-03-14 13:36:58Z snelsen $"
00002 
00003 //============================================================================
00004 //
00005 //  This file is part of GPSTk, the GPS Toolkit.
00006 //
00007 //  The GPSTk is free software; you can redistribute it and/or modify
00008 //  it under the terms of the GNU Lesser General Public License as published
00009 //  by the Free Software Foundation; either version 2.1 of the License, or
00010 //  any later version.
00011 //
00012 //  The GPSTk is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU Lesser General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU Lesser General Public
00018 //  License along with GPSTk; if not, write to the Free Software Foundation,
00019 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //  
00021 //  Copyright 2004, The University of Texas at Austin
00022 //
00023 //============================================================================
00024 
00025 //============================================================================
00026 //
00027 //This software developed by Applied Research Laboratories at the University of
00028 //Texas at Austin, under contract to an agency or agencies within the U.S. 
00029 //Department of Defense. The U.S. Government retains all rights to use,
00030 //duplicate, distribute, disclose, or release this software. 
00031 //
00032 //Pursuant to DoD Directive 523024 
00033 //
00034 // DISTRIBUTION STATEMENT A: This software has been approved for public 
00035 //                           release, distribution is unlimited.
00036 //
00037 //=============================================================================
00038 
00044 #include "StringUtils.hpp"
00045 #include "SMODFData.hpp"
00046 #include "SMODFStream.hpp"
00047 
00048 using namespace gpstk::StringUtils;
00049 using namespace std;
00050 
00051 namespace gpstk
00052 {
00053    const int SMODFData::SMO_LEN_ICD211 = 85;  
00054    const int SMODFData::SMO_LEN_LEGACY = 80;  
00055    const int SMODFData::BEGINGPS2DYEAR = 80;  
00056 
00057    void SMODFData::reallyPutRecord(gpstk::FFStream& ffs) const 
00058       throw(std::exception, gpstk::FFStreamError,
00059             gpstk::StringUtils::StringException)
00060    {
00061       SMODFStream& strm = dynamic_cast<SMODFStream&>(ffs);
00062       
00063       // here's a hack - if you dont know what to write, assume ICD211
00064       if (strm.format == SMODFStream::undefined)
00065          strm.format = SMODFStream::icd211;
00066       
00067       string line;
00068       
00069       if (strm.format == SMODFStream::icd211)
00070       {
00071          line += rightJustify(asString<short>(time.DOYyear()),4);
00072          line += rightJustify(asString<short>(time.DOYday()),3,'0');
00073          line += rightJustify(asString(time.DOYsecond(),7),13);
00074          line += rightJustify(asString<short>(PRNID),3);
00075          line += rightJustify(asString<long>(station),5);
00076          line += rightJustify(asString<short>(channel),2);
00077          line += rightJustify(asString<short>(type),1);
00078          
00079          if (type == 9)
00080             line += rightJustify(asString<short>(lol),1);
00081          else
00082             line += string(1, ' ');
00083          
00084          line += doub2funny(obs, 21, 2);
00085          line += doub2funny(stdDev, 12, 2);
00086          line += string(1, ' ');
00087          line += rightJustify(asString<short>(tempSource),1);
00088          line += rightJustify(asString<short>(pressSource),1);
00089          line += rightJustify(asString<short>(humidSource),1);
00090          line += rightJustify(asString(temp,1), 5);
00091          line += rightJustify(asString(pressure,1), 6);
00092          line += rightJustify(asString(humidity,1), 5);
00093          
00094       }
00095       else if (strm.format == SMODFStream::legacy)
00096       {
00097          line += time.printf("%02y%3j%12.6s");
00098          line += rightJustify(asString<short>(PRNID),3);
00099          line += rightJustify(asString<long>(station),5);
00100          line += rightJustify(asString<short>(channel),2);
00101          line += rightJustify(asString<short>(type),1);
00102          
00103          if (type == 9)
00104             line += rightJustify(asString<short>(lol),1);
00105          else
00106             line += string(1, ' ');
00107          
00108             // FIX this is actually D21.14, but because of the way
00109             // doub2for works, we prepend a space and use 20 characters
00110          line += string(1, ' ');
00111          line += doub2for(obs, 20, 2);
00112             // FIX same as above, only with D12.5
00113          line += string(1, ' ');
00114          line += doub2for(stdDev, 11, 2);
00115          line += string(1, ' ');
00116 
00117             // convert from 211-B/C to 211-A flags
00118          short wxsource = 0;
00119          if (tempSource == pressSource == humidSource)
00120             wxsource = tempSource;
00121          else if (tempSource && pressSource && humidSource)
00122          {
00123                // No missing data.  We can assume that there is some
00124                // default data at this point because the first test
00125                // eliminates the all-sources-same condition (all real,
00126                // all missing, all default), and this test guarantees
00127                // that there are no missing data mixed in with
00128                // real/default.  Only remaining possibility is some
00129                // real, some default.
00130             wxsource = 2;
00131          }
00132          else
00133          {
00134                // Mixed real and/or default data with missing.  We
00135                // can't really handle that.
00136             gpstk::FFStreamError err("Assertion failed: all weather data must be"
00137                               " either present or missing");
00138             if (tempSource == 0)
00139                err.addText("temperature data is missing");
00140             if (pressSource == 0)
00141                err.addText("pressure data is missing");
00142             if (humidSource == 0)
00143                err.addText("humidity data is missing");
00144             err.addText("unlisted weather measurements are present");
00145          }
00146 
00147          if (wxsource == 1)
00148             wxsource = 7;
00149 
00150          line += rightJustify(asString<short>(wxsource),1);
00151          line += rightJustify(asString(temp,1), 5);
00152          line += rightJustify(asString(pressure,1), 6);
00153          line += rightJustify(asString(humidity,1), 5);
00154       }
00155       else
00156       {
00157          gpstk::FFStreamError err("Unknown SMODF format: " + 
00158                            asString<unsigned long>(strm.format));
00159          err.addText("Make sure you specify the format of the data.");
00160          GPSTK_THROW(err);
00161       }
00162       
00163       ffs << line << endl;
00164       strm.lineNumber++;
00165    }
00166 
00167    void SMODFData::dump(ostream& s) const 
00168    {
00169       s << time << "  Station: " << station << "  Type: " << type 
00170         << "  PRN  " << PRNID  << endl;
00171    }
00172 
00173    void SMODFData::reallyGetRecord(gpstk::FFStream& ffs)
00174       throw(std::exception, gpstk::FFStreamError,
00175             gpstk::StringUtils::StringException)
00176    {
00177       SMODFStream& strm = dynamic_cast<SMODFStream&>(ffs);
00178 
00179       string str, currentLine;
00180       
00181       strm.formattedGetLine(currentLine, true);
00182       int len=currentLine.length();
00183 
00184          // determine the format of the ODBIF file by examining 
00185          // the record length
00186       if (strm.format == SMODFStream::undefined)
00187       {
00188          if (len == SMO_LEN_ICD211)
00189             strm.format = SMODFStream::icd211;
00190          else if (len == SMO_LEN_LEGACY)
00191             strm.format = SMODFStream::legacy;
00192          else
00193          {
00194             gpstk::FFStreamError e("Unreconized format");
00195             GPSTK_THROW(e);
00196          }
00197       }
00198       
00199       if (strm.format == SMODFStream::icd211)
00200       {
00201          if (len != SMO_LEN_ICD211)
00202          {
00203             gpstk::FFStreamError e("Bad 211 format line length: " + 
00204                             asString(len));
00205             GPSTK_THROW(e);
00206          }
00207          
00208             // blank out column 66 (in case this ODBIF file uses it 
00209             //   for some unauthorized purpose)
00210          currentLine[65] = ' ';
00211          
00212          if (currentLine[31]!='1')
00213             currentLine[31]='0';
00214          
00215             // Parse line and load apropriate values into ODBIF structure
00216          short year =     asInt(currentLine.substr( 0,  4));
00217          short DOY  =     asInt(currentLine.substr( 4,  3));
00218          double SOD =  asDouble(currentLine.substr( 7, 13));
00219          PRNID =          asInt(currentLine.substr(21,  2));
00220          station =        asInt(currentLine.substr(23,  5));
00221          channel =        asInt(currentLine.substr(28,  2));
00222          type =           asInt(currentLine.substr(30,  1));
00223          lol  =           asInt(currentLine.substr(31,  1));
00224          obs  =        for2doub(currentLine.substr(32, 21));
00225          stdDev =      for2doub(currentLine.substr(53, 12));
00226          tempSource =     asInt(currentLine.substr(66,  1));
00227          pressSource =    asInt(currentLine.substr(67,  1));
00228          humidSource =    asInt(currentLine.substr(68,  1));
00229          temp =        asDouble(currentLine.substr(69,  5));
00230          pressure =    asDouble(currentLine.substr(74,  6));
00231          humidity =    asDouble(currentLine.substr(80,  5));
00232 
00233          // Add some sanity checks on the data so we can detect if this is
00234          // *really* a SMOD file.
00235          if (DOY < 0 || DOY > 366 || SOD > 86400 || PRNID > 32 || 
00236              (type != 0 && type != 9) ||
00237              stdDev > 100 || stdDev <= 0)
00238          {
00239             gpstk::FFStreamError e(string("Bad 211 format data"));
00240             GPSTK_THROW(e);
00241          }
00242 
00243          
00244             // set the time
00245          time.setYDoySod(year, DOY, SOD);
00246       }
00247       else if (strm.format == SMODFStream::legacy)
00248       {
00249          if (len != SMO_LEN_LEGACY)
00250          {
00251             gpstk::FFStreamError e("Bad legacy format line length: " + 
00252                             asString(len));
00253             GPSTK_THROW(e);
00254          }
00255          
00256             // blank out column 63 (in case this ODBIF file uses it 
00257             // for some unauthorized purpose)
00258          currentLine[62] = ' ';
00259          
00260          if (currentLine[28]!='1')
00261             currentLine[28]='0';
00262          
00263             // Parse line and load apropriate values into ODBIF structure
00264          short year =     asInt(currentLine.substr( 0,  2));
00265          short DOY  =     asInt(currentLine.substr( 2,  3));
00266          double SOD =  asDouble(currentLine.substr( 5, 12));
00267          PRNID =          asInt(currentLine.substr(17,  3));
00268          station =        asInt(currentLine.substr(20,  5));
00269          channel =        asInt(currentLine.substr(25,  2));
00270          type =           asInt(currentLine.substr(27,  1));
00271          lol  =           asInt(currentLine.substr(28,  1));
00272          obs  =        for2doub(currentLine.substr(29, 21));// len ??
00273          stdDev =      for2doub(currentLine.substr(50, 12));//start & 
00274          short src =      asInt(currentLine.substr(63,  1));
00275          temp =        asDouble(currentLine.substr(64,  5));
00276          pressure =    asDouble(currentLine.substr(69,  6));
00277          humidity =    asDouble(currentLine.substr(75,  5));
00278 
00279          // Add some sanity checks on the data so we can detect if this is
00280          // *really* a SMOD file.
00281          if (DOY < 0 || DOY > 366 || SOD > 86400 || PRNID > 32 || 
00282              (type != 0 && type != 9) ||
00283              stdDev > 100 || stdDev <= 0)
00284          {
00285             gpstk::FFStreamError e(string("Bad legacy format data"));
00286             GPSTK_THROW(e);
00287          }
00288          
00289             // set the time
00290          if ( year < BEGINGPS2DYEAR )
00291             year += 2000;
00292          else 
00293             year += 1900;
00294          time.setYDoySod(year, DOY, SOD);
00295          
00296             /*
00297               Translate ODBIF (legacy) weather types to ICD-GPS-211 types
00298               Legacy   Meaning
00299               0     No met data
00300               1     OCS smoothed values
00301               2     OCS default values
00302               3     NIMA overridden at OCS (?)
00303               6     NIMA default weather values
00304               7     NIMA automated weather station (usual)
00305               8     Bad meteorological data
00306               other    Undefined
00307             */
00308          if ( src==1 || src==7 )
00309             tempSource = pressSource = humidSource = 1;
00310          else if ( src==2 || src==6 )
00311             tempSource = pressSource = humidSource = 2;
00312          else
00313             tempSource = pressSource = humidSource = 0;   
00314       }
00315    }   // end reallyGetRecord()
00316 
00317    string SMODFData::doub2funny(const double& num,
00318                                 const std::string::size_type length,
00319                                 const std::string::size_type expLen)
00320    {
00321          // Prepend a space if num > 0.
00322          // doub2sci() is supposed to do this, but it doesn't.
00323       string str((num >= 0 ? 1 : 0), ' ');
00324       str += doub2sci(num, length, expLen);
00325          // replace the 'e' or 'E' with 'D' as specified in the '211
00326       std::string::size_type idx = str.find_first_of("eE");
00327       if (idx != std::string::npos)
00328          str[idx] = 'D';
00329       return str;
00330    }
00331 
00332 } // end namespace gpstk

Generated on Wed Feb 8 03:31:02 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1