Program Listing for File readers.h

Return to documentation for file (source/io/readers.h)

/*
 * readers.h File readers for timeseries instrument data
 *
 * Author:                   Tom Clark (thclark @ github)
 *
 * Copyright (c) 2016-9 Octue Ltd. All Rights Reserved.
 *
 */
#ifndef ES_FLOW_READERS_H
#define ES_FLOW_READERS_H

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>
#include "matio.h"
#include "glog/logging.h"
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>
#include <eigen3/Eigen/Core>
#include "data_types.h"


namespace es {


// Level of data validation applied to timeseries. Exception is thrown if checks fail
enum timeseries_check_level {
    PRESENT             = 0,    // Checks that data is present and of correct type. Extracts start and end timestamps.
    INCREASING          = 1,    // As PRESENT + checks that the timestamp always increases.
    MONOTONIC           = 2,    // As INCREASING + checks that timestamp uniformly increases, allows data skip (e.g. instrument turned off then back on later). Extracts sampling frequency.
    STRICTLY_MONOTONIC  = 3,    // AS INCREASING + checks that timestamp uniformly increases, data skipping causes errors. Extracts sampling frequency.
};

// Level of data validation applied to file type. Exception is thrown if checks fail
enum file_type_check_level {
    NONE                = 0,    // No checks
    OAS_STANDARD        = 1,    // Checks that the file contains the 'type' string variable
};

template <class DataType>
class Reader {
public:

    Reader(const std::string &file);

    ~Reader();

    std::string logString() const;

    DataType *read(bool print=false);

    void checkFileType(int level);

    void checkTimeseries(int level);

    double getWindowDuration() const;

    void setWindowDuration(double windowDuration);

    int getWindowSize() const;

    void setWindowSize(int windowSize);

    void readWindow(const int index);

protected:

    std::string file;
    mat_t *matfp;
    std::string file_type = std::string("none");
    int windowSize;
    double windowDuration;
    DataType data;

};

template <class DataType>
Reader<DataType>::Reader(const std::string &file) : file(file) {

    // Open the MAT file for reading and save the pointer
    matfp = Mat_Open(file.c_str(), MAT_ACC_RDONLY);
    if (matfp == NULL) {
        std::string msg = "Error reading MAT file: ";
        throw std::invalid_argument(msg + file);
    }

}

template <class DataType>
Reader<DataType>::~Reader() {

    // Close the file on destruction of the Reader
    Mat_Close(matfp);

}

template <class DataType>
void Reader<DataType>::checkFileType(int level){

    // Get the file type from the reserved 'type' variable in the mat file
    matvar_t *type_var = Mat_VarRead(matfp, "type");
    if (type_var == NULL) {
        if (level == OAS_STANDARD) {
            throw std::invalid_argument("Error reading mat file (most likely not an OAS standard file format - 'type' variable is missing)");
        }
    } else {
        if (type_var->class_type != MAT_C_CHAR) {
            throw std::invalid_argument("Error reading mat file ('type' variable must be a character array)");
        }
        file_type = std::string((const char*)type_var->data, type_var->dims[1]);
    }

}

template <class DataType>
void Reader<DataType>::checkTimeseries(int level) {

    // Check the integrity of the timeseries, automatically determine dt and frequency where possible

}

template <class DataType>
double Reader<DataType>::getWindowDuration() const {
    return windowDuration;
}

template <class DataType>
void Reader<DataType>::setWindowDuration(double windowDuration) {
    Reader<DataType>::windowDuration = windowDuration;
}

template <class DataType>
int Reader<DataType>::getWindowSize() const {
    return windowSize;
}

template <class DataType>
void Reader<DataType>::setWindowSize(int windowSize) {
    Reader<DataType>::windowSize = windowSize;
}

template <class DataType>
std::string Reader<DataType>::logString() const {
    return std::string("Object Reader for type ") + file_type + std::string(", attached to file ") + file;
}

template <class DataType>
DataType *Reader<DataType>::read(bool print) {
    // Simply invoke the read method of the DataType class.
    if (std::strcmp(data.type.c_str(), file_type.c_str())) {
        std::string msg = "Mat file type '" + file_type + "' incompatible with the specified data type '" + data.type + "'";
        throw std::invalid_argument(msg);
    }
    data.read(matfp, print);
    return &data;
}

template <class DataType>
void Reader<DataType>::readWindow(const int index) {
    //<DataType>.read(file_type, matfp);
}

// Represent Reader classes in logs or ostream
template <class DataType>
::std::ostream& operator<<(::std::ostream& os, const Reader<DataType>& reader) {
    // Represent in logs or ostream
    return os << reader.logString();
}

} /* namespace es */



#endif // ES_FLOW_READERS_H