From ca72abd9f739b4e6647470e0ea30e6f70af59872 Mon Sep 17 00:00:00 2001 From: Zach Cobell Date: Sat, 29 Jun 2019 17:05:07 -0400 Subject: [PATCH] Adding processing to MetOceanData to create netCDF CRMS database --- MetOceanData/MetOceanData.pro | 2 + MetOceanData/main.cpp | 11 +++- MetOceanData/metoceandata.cpp | 85 ++++++++++++++++++-------- MetOceanData/metoceandata.h | 10 ++- MetOceanData/options.cpp | 23 ++++++- MetOceanData/options.h | 2 + MetOceanData/optionslist.h | 7 ++- libraries/libmetocean/crmsdatabase.cpp | 18 +++--- libraries/libmetocean/crmsdatabase.h | 11 ++-- 9 files changed, 121 insertions(+), 48 deletions(-) diff --git a/MetOceanData/MetOceanData.pro b/MetOceanData/MetOceanData.pro index 5ac96bb8..8dc96e36 100644 --- a/MetOceanData/MetOceanData.pro +++ b/MetOceanData/MetOceanData.pro @@ -26,6 +26,8 @@ CONFIG += c++11 console CONFIG -= app_bundle TARGET = MetOceanData +INCLUDEPATH += $$PWD/../thirdparty/boost_1_67_0 + # The following define makes your compiler emit warnings if you use # any feature of Qt which as been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the diff --git a/MetOceanData/main.cpp b/MetOceanData/main.cpp index 934dddda..b23b24f9 100644 --- a/MetOceanData/main.cpp +++ b/MetOceanData/main.cpp @@ -42,11 +42,16 @@ int main(int argc, char *argv[]) { option->processOptions(); Options::CommandLineOptions opt = option->getCommandLineOptions(); - MetOceanData *d = - new MetOceanData(opt.service, opt.station, opt.product, opt.datum, - opt.startDate, opt.endDate, opt.outputFile, &a); + MetOceanData *d; + if (opt.doCrms) { + d = new MetOceanData(opt.crms, opt.outputFile, &a); + } else { + d = new MetOceanData(opt.service, opt.station, opt.product, opt.datum, + opt.startDate, opt.endDate, opt.outputFile, &a); + } d->setLoggingActive(); QObject::connect(d, SIGNAL(finished()), &a, SLOT(quit())); QTimer::singleShot(0, d, SLOT(run())); + return a.exec(); } diff --git a/MetOceanData/metoceandata.cpp b/MetOceanData/metoceandata.cpp index 8cd38417..cd86f9cc 100644 --- a/MetOceanData/metoceandata.cpp +++ b/MetOceanData/metoceandata.cpp @@ -22,6 +22,7 @@ #include #include #include "constants.h" +#include "crmsdatabase.h" #include "generic.h" #include "hmdf.h" #include "ndbcdata.h" @@ -34,16 +35,17 @@ static const QHash noaaProducts = { {4, "air_temperature"}, {5, "water_temperature"}, {6, "wind:speed"}, {7, "humidity"}, {8, "air_pressure"}, {9, "wind:direction"}, {10, "wind:gusts"}}; -static const QHash noaaProductLongName = {{1, "6 minute water level"}, - {2, "Hourly water level"}, - {3, "Tide predictoins"}, - {4, "Air temperature"}, - {5, "Water temperature"}, - {6, "Wind speed"}, - {7, "Humidity"}, - {8, "Air pressure"}, - {9, "Wind direction"}, - {10, "Wind gusts"}}; +static const QHash noaaProductLongName = { + {1, "6 minute water level"}, + {2, "Hourly water level"}, + {3, "Tide predictoins"}, + {4, "Air temperature"}, + {5, "Water temperature"}, + {6, "Wind speed"}, + {7, "Humidity"}, + {8, "Air pressure"}, + {9, "Wind direction"}, + {10, "Wind gusts"}}; static const QHash noaaUnits = { {1, "m"}, {2, "m"}, {3, "m"}, {4, "C"}, {5, "C"}, {6, "m/s"}, {7, "%"}, {8, "mb"}, {9, "deg"}, {10, "m/s"}}; @@ -59,6 +61,8 @@ MetOceanData::MetOceanData(QObject *parent) : QObject(parent) { this->m_startDate = QDateTime(); this->m_endDate = QDateTime(); this->m_outputFile = QString(); + this->m_doCrms = false; + this->m_crmsFile = QString(); } MetOceanData::MetOceanData(serviceTypes service, QStringList station, @@ -73,6 +77,22 @@ MetOceanData::MetOceanData(serviceTypes service, QStringList station, this->m_startDate = startDate; this->m_endDate = endDate; this->m_outputFile = outputFile; + this->m_doCrms = false; + this->m_crmsFile = QString(); +} + +MetOceanData::MetOceanData(QString crmsFile, QString outputFile, + QObject *parent) + : QObject(parent) { + this->m_service = 0; + this->m_product = 0; + this->m_datum = 0; + this->m_station = QStringList(); + this->m_startDate = QDateTime(); + this->m_endDate = QDateTime(); + this->m_outputFile = outputFile; + this->m_doCrms = true; + this->m_crmsFile = crmsFile; } int MetOceanData::service() const { return m_service; } @@ -137,23 +157,27 @@ void MetOceanData::showStatus(QString message, int pct) { } void MetOceanData::run() { - if (this->service() == USGS && this->m_station.length() > 1) { - emit error( - "Beacuase each station has different characteristics, only one " - "USGS station may be selected at a time."); - emit finished(); + if (this->m_doCrms) { + this->processCrmsData(); return; - } - - if (this->service() == NOAA) - this->getNoaaData(); - else if (this->service() == USGS) - this->getUsgsData(); - else if (this->service() == NDBC) - this->getNdbcData(); - else if (this->service() == XTIDE) - this->getXtideData(); + } else { + if (this->service() == USGS && this->m_station.length() > 1) { + emit error( + "Beacuase each station has different characteristics, only one " + "USGS station may be selected at a time."); + emit finished(); + return; + } + if (this->service() == NOAA) + this->getNoaaData(); + else if (this->service() == USGS) + this->getUsgsData(); + else if (this->service() == NDBC) + this->getNdbcData(); + else if (this->service() == XTIDE) + this->getXtideData(); + } emit finished(); return; } @@ -502,3 +526,14 @@ QString MetOceanData::noaaIndexToUnits() { return noaaUnits[this->m_product]; } int MetOceanData::getDatum() const { return m_datum; } void MetOceanData::setDatum(int datum) { m_datum = datum; } + +void MetOceanData::processCrmsData() { + CrmsDatabase *d = new CrmsDatabase(this->m_crmsFile.toStdString(), + this->m_outputFile.toStdString(), this); + connect(d, SIGNAL(error(QString)), this, SLOT(showError(QString))); + d->setShowProgressBar(true); + d->parse(); + emit finished(); + delete d; + return; +} diff --git a/MetOceanData/metoceandata.h b/MetOceanData/metoceandata.h index db4e4bb6..338708a6 100644 --- a/MetOceanData/metoceandata.h +++ b/MetOceanData/metoceandata.h @@ -35,6 +35,8 @@ class MetOceanData : public QObject { explicit MetOceanData(serviceTypes service, QStringList station, int product, int datum, QDateTime startDate, QDateTime endDate, QString outputFile, QObject *parent = nullptr); + explicit MetOceanData(QString crmsFile, QString outputFile, + QObject *parent = nullptr); static QStringList selectStations(serviceTypes service, double x1, double y1, double x2, double y2); @@ -62,9 +64,10 @@ class MetOceanData : public QObject { int getDatum() const; void setDatum(int datum); - static StationLocations::MarkerType serviceToMarkerType(MetOceanData::serviceTypes type); + static StationLocations::MarkerType serviceToMarkerType( + MetOceanData::serviceTypes type); static bool findStation(QStringList name, StationLocations::MarkerType type, - QVector &s); + QVector &s); signals: void finished(); @@ -83,6 +86,7 @@ class MetOceanData : public QObject { void getUsgsData(); void getNdbcData(); void getXtideData(); + void processCrmsData(); QString noaaIndexToProduct(); QString noaaIndexToDatum(); @@ -90,6 +94,7 @@ class MetOceanData : public QObject { int printAvailableProducts(Hmdf *data); + bool m_doCrms; int m_service; QStringList m_station; int m_product; @@ -97,6 +102,7 @@ class MetOceanData : public QObject { QDateTime m_startDate; QDateTime m_endDate; QString m_outputFile; + QString m_crmsFile; }; #endif // DRIVER_H diff --git a/MetOceanData/options.cpp b/MetOceanData/options.cpp index 665339a4..74690690 100644 --- a/MetOceanData/options.cpp +++ b/MetOceanData/options.cpp @@ -37,12 +37,25 @@ void Options::addOptions() { << m_serviceType << m_stationId << m_boundingBox << m_nearest << m_startDate << m_endDate << m_product << m_outputFile << m_datum << m_list - << m_show); + << m_show << m_crmsSourceFile); } Options::CommandLineOptions Options::getCommandLineOptions() { Options::CommandLineOptions opt; + opt.doCrms = false; + + if (this->parser()->isSet(m_crmsSourceFile)) { + if (!this->parser()->isSet(m_outputFile)) { + std::cerr << "No output file set." << std::endl; + this->parser()->showHelp(1); + } + opt.crms = this->parser()->value(m_crmsSourceFile); + opt.outputFile = this->parser()->value(m_outputFile); + opt.doCrms = true; + return opt; + } + std::vector inputOptions; inputOptions.push_back(this->parser()->isSet(m_stationId)); inputOptions.push_back(this->parser()->isSet(m_boundingBox)); @@ -238,8 +251,12 @@ void Options::printStationList(QStringList station, MetOceanData::serviceToMarkerType(markerType), s); for (size_t i = 0; i < station.size(); ++i) { std::cout << s[i].id().toStdString() << ",'" - << s[i].name().replace(" ", "_").replace(",","_").replace("__","_").toStdString() << "'," - << s[i].coordinate().longitude() << "," + << s[i].name() + .replace(" ", "_") + .replace(",", "_") + .replace("__", "_") + .toStdString() + << "'," << s[i].coordinate().longitude() << "," << s[i].coordinate().latitude() << std::endl; std::cout.flush(); } diff --git a/MetOceanData/options.h b/MetOceanData/options.h index 04ce3ab8..be74be22 100644 --- a/MetOceanData/options.h +++ b/MetOceanData/options.h @@ -38,6 +38,8 @@ class Options : public QObject { QDateTime endDate; QString outputFile; QStringList station; + bool doCrms; + QString crms; }; void processOptions(); diff --git a/MetOceanData/optionslist.h b/MetOceanData/optionslist.h index 628d26b3..05e12ab3 100644 --- a/MetOceanData/optionslist.h +++ b/MetOceanData/optionslist.h @@ -72,7 +72,8 @@ static const QCommandLineOption m_outputFile = QCommandLineOption(QStringList() << "o" << "output", "Name of the output file. Format will be guessed from " - "extension (.imeds or .nc)", + "extension (.imeds or .nc). Note if performing crms " + "processing, the output extension will always be *.nc", "filename"); static const QCommandLineOption m_boundingBox = @@ -96,4 +97,8 @@ static const QCommandLineOption m_show = "Show the stations that would be selected given the " "provided criteria and exit."); +static const QCommandLineOption m_crmsSourceFile = QCommandLineOption( + QStringList() << "crms", "Converts a CRMS database into netCDF format", + "filename"); + #endif // OPTIONSLIST_H diff --git a/libraries/libmetocean/crmsdatabase.cpp b/libraries/libmetocean/crmsdatabase.cpp index c7876df1..784729b8 100644 --- a/libraries/libmetocean/crmsdatabase.cpp +++ b/libraries/libmetocean/crmsdatabase.cpp @@ -43,10 +43,9 @@ CrmsDatabase::CrmsDatabase(const std::string &datafile, m_hasError(false), m_showProgressBar(false), m_progressbar(nullptr), + m_previousPercentComplete(0), QObject(parent) {} -float CrmsDatabase::fillValue() const { return -9999.0f; } - double CrmsDatabase::getPercentComplete() { size_t fileposition = static_cast(this->m_file.tellg()); double percent = @@ -55,18 +54,19 @@ double CrmsDatabase::getPercentComplete() { 100.0; emit this->percentComplete(static_cast(std::floor(percent))); if (this->m_showProgressBar) { - unsigned long dt = - static_cast(std::floor(std::round(percent))) - - this->m_previousPercentComplete; - *(this->m_progressbar) += dt; - this->m_previousPercentComplete += dt; + unsigned long dt = static_cast(std::floor(percent)) - + this->m_previousPercentComplete; + if (dt > 0) { + *(this->m_progressbar) += dt; + this->m_previousPercentComplete += dt; + } } return percent; } void CrmsDatabase::parse() { if (!this->fileExists(this->m_databaseFile)) { - emit error(); + emit error("File does not exist"); emit complete(); return; } @@ -103,7 +103,7 @@ void CrmsDatabase::parse() { this->closeCrmsFile(); if (this->m_hasError) { - emit error(); + emit error("Error during CRMS processing"); emit this->percentComplete(0); } else { emit success(); diff --git a/libraries/libmetocean/crmsdatabase.h b/libraries/libmetocean/crmsdatabase.h index 861033af..878e976e 100644 --- a/libraries/libmetocean/crmsdatabase.h +++ b/libraries/libmetocean/crmsdatabase.h @@ -17,8 +17,8 @@ // along with this program. If not, see . // //-----------------------------------------------------------------------*/ -#ifndef READCRMSDATABASE_H -#define READCRMSDATABASE_H +#ifndef CRMSDATABASE_H +#define CRMSDATABASE_H #include #include @@ -39,6 +39,8 @@ class CrmsDatabase : public QObject { bool showProgressBar() const; void setShowProgressBar(bool showProgressBar); + static constexpr float fillValue() { return -9999.0f; } + public slots: void parse(); @@ -46,7 +48,7 @@ class CrmsDatabase : public QObject { void percentComplete(int); void complete(); void success(); - void error(); + void error(QString); private: struct Position { @@ -74,7 +76,6 @@ class CrmsDatabase : public QObject { void initializeOutputFile(); void closeOutputFile(size_t numStations); bool fileExists(const std::string &filename); - float fillValue() const; void exitCleanly(); std::string m_databaseFile; @@ -93,4 +94,4 @@ class CrmsDatabase : public QObject { size_t m_fileLength; }; -#endif // READCRMSDATABASE_H +#endif // CRMSDATABASE_H