Multi-approach gravity field models from Swarm GPS data


© 2017 Institute of Geodesy of the Technical University of Graz

All rights reserved. This code or any portion thereof may not be reproduced or used in any manner whatsoever without the express written permission of the copyright owner.

/***********************************************/
/**
* @file fileSinex.h
*
* @brief SINEX file representation.
*
* @author Sebastian Strasser
* @date 2017-05-15
*
*/
/***********************************************/

#ifndef __GROOPS_FILESINEX__
#define __GROOPS_FILESINEX__

#include "base/import.h"
#include "base/parameterName.h"
#include "base/fileName.h"
#include "config/config.h"
#include "config/logging.h"

/***** CLASS ***********************************/

/** @brief SINEX file representation. */
class Sinex
{
  enum BlockType
  {
    UNKNOWN,
    FILE_REFERENCE,
    FILE_COMMENT,
    INPUT_HISTORY,
    INPUT_FILES,
    INPUT_ACKNOWLEDGEMENTS,
    NUTATION_DATA,
    PRECESSION_DATA,
    SOURCE_ID,
    SITE_ID,
    SITE_DATA,
    SITE_RECEIVER,
    SITE_ANTENNA,
    SITE_GPS_PHASE_CENTER,
    SITE_GAL_PHASE_CENTER,
    SITE_ECCENTRICITY,
    SATELLITE_ID,
    SATELLITE_PHASE_CENTER,
    BIAS_EPOCHS,
    SOLUTION_EPOCHS,
    SOLUTION_STATISTICS,
    SOLUTION_ESTIMATE,
    SOLUTION_APRIORI,
    SOLUTION_MATRIX_ESTIMATE,
    SOLUTION_MATRIX_APRIORI,
    SOLUTION_NORMAL_EQUATION_VECTOR,
    SOLUTION_NORMAL_EQUATION_MATRIX
  };

  class SinexBlock;
  typedef std::shared_ptr<SinexBlock> SinexBlockPtr;

  std::string _header;                        /// SINEX file header line
  std::map<BlockType, SinexBlockPtr> _blocks; /// SINEX blocks

  static BlockType blockType(const std::string &label);

public:
  class Parameter;
  class SinexText;
  class SinexSolutionVector;
  class SinexSolutionMatrix;
  class SinexSolutionStatistics;
  typedef std::shared_ptr<SinexText>               SinexTextPtr;
  typedef std::shared_ptr<SinexSolutionVector>     SinexSolutionVectorPtr;
  typedef std::shared_ptr<SinexSolutionMatrix>     SinexSolutionMatrixPtr;
  typedef std::shared_ptr<SinexSolutionStatistics> SinexSolutionStatisticsPtr;

  Sinex() {}
  Sinex(const FileName &fileName) { readFile(fileName); }

  // read and write related
  void        readConfigHeader(Config &config);
  std::string header() const;
  void        readFile(const FileName &fileName);
  void        writeFile(const FileName &fileName) const;

  // block related
  Bool hasBlock(const std::string &label) const { return (_blocks.find(blockType(label)) != _blocks.end()); }
  template<typename T> std::shared_ptr<T> addBlock(const std::string &label);
  template<typename T> std::shared_ptr<T> getBlock(const std::string &label) const;

  // conversion
  static std::string time2str(const Time &time);
  static Time        str2time(const std::string &line, size_t pos, size_t len);
};

/***********************************************/

/** @brief SINEX vector block line/entry. */
class Sinex::Parameter
{
public:
  UInt        parameterIndex;
  std::string parameterType;
  std::string siteCode;
  std::string pointCode;
  std::string solutionId;
  Time        time;
  std::string unit;
  std::string constraintCode;
  Double      value;
  Double      sigma;

  Parameter() : parameterIndex(0), value(0), sigma(0) {}
};

/***********************************************/

/** @brief SINEX base block representation. */
class Sinex::SinexBlock
{
  std::string _label;
  BlockType   _blockType;

protected:
  virtual BlockType blockType() const { return _blockType; }

public:
  SinexBlock(const std::string &label) : _label(label), _blockType(Sinex::blockType(label)) {}
  virtual ~SinexBlock() {}
  virtual std::string header()    const = 0;
  virtual std::string label()     const { return _label; }
  virtual void        readLine(const std::string &line) = 0;
  virtual Bool        writeBlock(std::ostream &file) const = 0;
};

/***********************************************/

/** @brief SINEX text block representation. */
class Sinex::SinexText : public Sinex::SinexBlock
{
  std::vector<std::string> _lines;

public:
  SinexText(const std::string &label) : SinexBlock(label) {}
  virtual std::string header() const;
  virtual void        readLine(const std::string &line) { _lines.push_back(line); }
  virtual Bool        writeBlock(std::ostream &file) const;
  virtual UInt        size()   const { return _lines.size(); }
  virtual std::vector<std::string> lines() const { return _lines; }
};

/***********************************************/

/** @brief SINEX vector block representation. */
class Sinex::SinexSolutionVector : public Sinex::SinexBlock
{
  std::vector<Parameter> _parameters;

public:
  SinexSolutionVector(const std::string &label) : SinexBlock(label) {}
  virtual std::string header() const;
  virtual void        readLine(const std::string &line);
  virtual Bool        writeBlock(std::ostream &file) const;
  virtual UInt        size()   const { return _parameters.size(); }
  virtual Vector      vector() const;
  virtual void        addParameter(Parameter parameter) { _parameters.push_back(parameter); }
  virtual std::vector<ParameterName> parameterNames() const;
  virtual std::vector<Parameter>     parameters()     const { return _parameters; }
};

/***********************************************/

/** @brief SINEX matrix block representation. */
class Sinex::SinexSolutionMatrix : public Sinex::SinexBlock
{
public:
  enum Type { CORRELATION, COVARIANCE, INFORMATION };

  Matrix _matrix;
  Type   _type;

  SinexSolutionMatrix(const std::string &label, const UInt size);
  virtual std::string label()  const;
  virtual std::string header() const { return "*PARA1 PARA2 _______PARA2+0_______ _______PARA2+1_______ _______PARA2+2_______"; }
  virtual void        readLine(const std::string &line);
  virtual Bool        writeBlock(std::ostream &file) const;
  virtual Type        type()   const { return _type; }
  virtual Matrix      matrix() const { return _matrix; }
  virtual void        setMatrix(const_MatrixSliceRef matrix, Type type = INFORMATION) { _matrix = matrix; _type = type; }
};

/***********************************************/

/** @brief SINEX solution statistics block representation. */
class Sinex::SinexSolutionStatistics : public Sinex::SinexBlock
{
  std::map<std::string, Double> _values;

public:
  SinexSolutionStatistics(const std::string &label) : SinexBlock(label) {}
  virtual std::string header() const { return "*____STATISTICAL_PARAMETER_____ _______VALUE(S)_______"; }
  virtual void        readLine(const std::string &line);
  virtual Bool        writeBlock(std::ostream &file) const;
  virtual Double      value(const std::string &name)  const;
  virtual void        addValue(const std::string &name, Double value) { _values[name] = value; }
};

/***********************************************/

template<typename T>
std::shared_ptr<T> Sinex::addBlock(const std::string &label)
{
  try
  {
    BlockType type = blockType(label);
    if(_blocks.find(type) != _blocks.end())
      throw(Exception("SINEX block already exists: " + label));

    if(     type == FILE_REFERENCE)                   _blocks[type] = SinexBlockPtr(new SinexText(label));
    else if(type == FILE_COMMENT)                     _blocks[type] = SinexBlockPtr(new SinexText(label));
    else if(type == INPUT_HISTORY)                    _blocks[type] = SinexBlockPtr(new SinexText(label));
    else if(type == INPUT_FILES)                      _blocks[type] = SinexBlockPtr(new SinexText(label));
    else if(type == INPUT_ACKNOWLEDGEMENTS)           _blocks[type] = SinexBlockPtr(new SinexText(label));
    else if(type == NUTATION_DATA)                    logWarning << "SINEX block not implemented yet: " << label << Log::endl;
    else if(type == PRECESSION_DATA)                  logWarning << "SINEX block not implemented yet: " << label << Log::endl;
    else if(type == SOURCE_ID)                        logWarning << "SINEX block not implemented yet: " << label << Log::endl;
    else if(type == SITE_ID)                          _blocks[type] = SinexBlockPtr(new SinexText(label));
    else if(type == SITE_DATA)                        logWarning << "SINEX block not implemented yet: " << label << Log::endl;
    else if(type == SITE_RECEIVER)                    _blocks[type] = SinexBlockPtr(new SinexText(label));
    else if(type == SITE_ANTENNA)                     _blocks[type] = SinexBlockPtr(new SinexText(label));
    else if(type == SITE_GPS_PHASE_CENTER)            _blocks[type] = SinexBlockPtr(new SinexText(label));
    else if(type == SITE_GAL_PHASE_CENTER)            logWarning << "SINEX block not implemented yet: " << label << Log::endl;
    else if(type == SITE_ECCENTRICITY)                _blocks[type] = SinexBlockPtr(new SinexText(label));
    else if(type == SATELLITE_ID)                     _blocks[type] = SinexBlockPtr(new SinexText(label));
    else if(type == SATELLITE_PHASE_CENTER)           _blocks[type] = SinexBlockPtr(new SinexText(label));
    else if(type == BIAS_EPOCHS)                      logWarning << "SINEX block not implemented yet: " << label << Log::endl;
    else if(type == SOLUTION_EPOCHS)                  _blocks[type] = SinexBlockPtr(new SinexText(label));
    else if(type == SOLUTION_STATISTICS)              _blocks[type] = SinexBlockPtr(new SinexSolutionStatistics(label));
    else if(type == SOLUTION_ESTIMATE)                _blocks[type] = SinexBlockPtr(new SinexSolutionVector(label));
    else if(type == SOLUTION_APRIORI)                 _blocks[type] = SinexBlockPtr(new SinexSolutionVector(label));
    else if(type == SOLUTION_MATRIX_ESTIMATE)         _blocks[type] = SinexBlockPtr(new SinexSolutionMatrix(label, getBlock<SinexSolutionVector>("SOLUTION/ESTIMATE")->size()));
    else if(type == SOLUTION_MATRIX_APRIORI)          _blocks[type] = SinexBlockPtr(new SinexSolutionMatrix(label, getBlock<SinexSolutionVector>("SOLUTION/APRIORI")->size()));
    else if(type == SOLUTION_NORMAL_EQUATION_VECTOR)  _blocks[type] = SinexBlockPtr(new SinexSolutionVector(label));
    else if(type == SOLUTION_NORMAL_EQUATION_MATRIX)  _blocks[type] = SinexBlockPtr(new SinexSolutionMatrix(label, getBlock<SinexSolutionVector>("SOLUTION/NORMAL_EQUATION_VECTOR")->size()));
    else
      logWarning << "Cannot add unknown SINEX block: " << label << Log::endl;

    if(_blocks.find(type) != _blocks.end())
      return std::dynamic_pointer_cast<T>(_blocks.at(type));
    else
      return nullptr;
  }
  catch(std::exception &e)
  {
    rethrow(e);
  }
}

/***********************************************/

template<typename T>
std::shared_ptr<T> Sinex::getBlock(const std::string &label) const
{
  try
  {
    auto iter = _blocks.find(blockType(label));
    if(iter == _blocks.end())
      throw(Exception("SINEX block not found: "+label));

    std::shared_ptr<T> t = std::dynamic_pointer_cast<T>(iter->second);
    if(t == nullptr)
      throw(Exception("Cannot cast to requested block type: "+label));
    return t;
  }
  catch(std::exception &e)
  {
    rethrow(e);
  }
}

/***********************************************/

#endif /* __GROOPS__ */