Tutorials

Under construction

Adding a new input format

If the existing dataset formats are not suitable, you can write your own interface. Other users of COMPS have written specialized interfaces to MySQL databases.

This example adds a new data format, which uses one variable in each column of the text file and one forecast offset in the row. This class inherits the functionality of $COMPS/src/Inputs/Input.h and overrides the required function getValueCore. The header file $COMPS/src/Inputs/New.h looks like:

#ifndef INPUT_NEW_H
#define INPUT_NEW_H
#include "Input.h"

class InputNew : public Input {
   public:
      InputNew(const Options& iOptions, const Data& iData);
   protected:
      // Return the value in the dataset corresponding to the date, offset, 
      // variable, ensemble member in iKey
      float getValueCore(const Key::Input& iKey) const;
      // Helper function to determine the filename corresponding to iKey
      std::string getFilename(const Key::Input& iKey) const;
};
#endif
The implementation file $COMPS/src/Inputs/New.cpp looks like:
#include "New.h"
#include "../Member.h"
#include "../Location.h"
#include "../Options.h"

InputNew::InputNew(const Options& iOptions, const Data& iData) : Input(iOptions, iData) {
   // All inputs must call this function
   init();
}

float InputNew::getValueCore(const Key::Input& iKey) const {
   float returnValue = Global::MV;

   // Open the file
   std::string filename = getFilename(iKey);
   std::ifstream ifs(filename.c_str(), std::ifstream::in);

   if(!ifs.good()) {
      // Missing file
      std::vector<float> values;
      Key::Input key = iKey;
      int offsetId = getOffsetIndex(iKey.offset);
      for(int i  = mCacheOtherOffsets ? 0 : offsetId;
              i <= (mCacheOtherOffsets ? mOffsets.size()-1 : offsetId) ;
              i++) {
         key.offset = mOffsets[iKey.offset];
         for(key.member = mCacheOtherMembers ? 0 : iKey.member;
             key.member <= (mCacheOtherMembers ? mMembers.size() - 1 : iKey.member);
             key.member++) {
            Input::addToCache(key, Global::MV);
         }
      }
   }
   else {
      // Loop over each line
      Key::Input key = iKey;
      int offsetId = 0;
      while(ifs.good()) {
         key.offset = mOffsets[offsetId];
         char line[10000];
         ifs.getline(line, 10000, '\n');
         if(ifs.good() && line[0] != '#') {
            std::stringstream ss(line);
            // Loop over each value
            key.member = 0;
            while(ss.good()) {
               float value;
               if(ss >> value) {
                  Input::addToCache(key, value);
               }
               if(key.offset == iKey.offset && key.member == iKey.member) {
                  returnValue = value;
               }
               key.member++;
            }
         }
         offsetId++;
      }
   }
   return returnValue;
}

std::string InputNew::getFilename(const Key::Input& iKey) const {
   std::stringstream ss(std::stringstream::out);
   std::string localVariableName = mId2LocalVariable[iKey.variable];
   assert(iKey.location < mLocations.size());
   int locationNum = mLocations[iKey.location].getId();
   ss << mDataDirectory << iKey.date << "_" << locationNum << "_" << localVariableName;
   return ss.str();
}