Browse Source

Redone abstractions

interpolate
Michael Uleysky 2 years ago
parent
commit
8906f25927
  1. 305
      include/NEMO.h
  2. 7
      include/ParseArgs.h
  3. 24
      include/basedata.h
  4. 180
      include/odm.h
  5. 13
      include/simple2ddata.h
  6. 63
      include/tindexes.h
  7. 118
      include/vartype.h
  8. 5
      src/ParseArgs.cpp
  9. 45
      src/actioninfo.cpp
  10. 165
      src/actiontsc.cpp
  11. 3
      src/basedata.cpp
  12. 23
      src/odm.cpp

305
include/NEMO.h

@ -1,16 +1,19 @@
#pragma once
#include "DataAdapters/ncfilealt.h"
#include "ParseArgs.h"
#include "mdatetime.h"
#include "simple2ddata.h"
#include "specfunc.h"
#include "vartype.h"
#include <memory>
#include <regex.h>
#include <set>
#include <stdlib.h>
#include <sys/types.h>
using michlib::Ceil;
using michlib::errmessage;
using michlib::Floor;
using michlib::GPL;
using michlib::int2;
using michlib::MDateTime;
using michlib::NCFileA;
@ -26,11 +29,19 @@ class NEMOData
TYPE_NRT6
};
struct Parameters: public BaseParameters
{
size_t xb, yb, xe, ye, layer;
MString varname;
virtual ~Parameters() override = default;
};
std::vector<NCFileA> nc;
size_t xb, yb, xe, ye, layer;
std::vector<real> depths;
std::vector<MDateTime> times;
size_t nx;
size_t nx, ny;
real lonb, latb, lone, late;
real lonstep, latstep;
Type type = TYPE_UNKNOWN;
class EnvVar
@ -73,7 +84,7 @@ class NEMOData
using Data = Simple2DData;
private:
template<class DataType> Data ReadVarRaw(const NCFileA& f, const MString& name, size_t i, bool nodepth) const
template<class DataType> Data ReadVarRaw(const NCFileA& f, const MString& name, size_t i, bool nodepth, const Parameters* p) const
{
real unitmul = 1.0;
DataType fill;
@ -92,12 +103,12 @@ class NEMOData
auto unit = f.A<MString>(name, "units");
if(unit && unit.Get() == "m s-1") unitmul = 100.0;
Data data((xb < xe) ? (xe - xb + 1) : (nx + xe - xb + 1), ye - yb + 1, Lonb(), Latb(), 1.0 / 12.0, 1.0 / 12.0);
Data data((p->xb < p->xe) ? (p->xe - p->xb + 1) : (nx + p->xe - p->xb + 1), p->ye - p->yb + 1, Lon(p->xb), Lat(p->yb), lonstep, latstep);
if(xb < xe)
if(p->xb < p->xe)
{
auto var = nodepth ? f.V<DataType>(name, {"longitude", xb, xe - xb + 1}, {"latitude", yb, ye - yb + 1}, {"time", i, 1})
: f.V<DataType>(name, {"longitude", xb, xe - xb + 1}, {"latitude", yb, ye - yb + 1}, {"time", i, 1}, {"depth", layer, 1});
auto var = nodepth ? f.V<DataType>(name, {"longitude", p->xb, p->xe - p->xb + 1}, {"latitude", p->yb, p->ye - p->yb + 1}, {"time", i, 1})
: f.V<DataType>(name, {"longitude", p->xb, p->xe - p->xb + 1}, {"latitude", p->yb, p->ye - p->yb + 1}, {"time", i, 1}, {"depth", p->layer, 1});
if(!var) return Data();
if(var.DimLen(0) != data.Nx() || var.DimLen(1) != data.Ny()) return Data();
@ -110,10 +121,10 @@ class NEMOData
}
else
{
auto var1 = nodepth ? f.V<DataType>(name, {"longitude", xb}, {"latitude", yb, ye - yb + 1}, {"time", i, 1})
: f.V<DataType>(name, {"longitude", xb}, {"latitude", yb, ye - yb + 1}, {"time", i, 1}, {"depth", layer, 1});
auto var2 = nodepth ? f.V<DataType>(name, {"longitude", 0, xe + 1}, {"latitude", yb, ye - yb + 1}, {"time", i, 1})
: f.V<DataType>(name, {"longitude", 0, xe + 1}, {"latitude", yb, ye - yb + 1}, {"time", i, 1}, {"depth", layer, 1});
auto var1 = nodepth ? f.V<DataType>(name, {"longitude", p->xb}, {"latitude", p->yb, p->ye - p->yb + 1}, {"time", i, 1})
: f.V<DataType>(name, {"longitude", p->xb}, {"latitude", p->yb, p->ye - p->yb + 1}, {"time", i, 1}, {"depth", p->layer, 1});
auto var2 = nodepth ? f.V<DataType>(name, {"longitude", 0, p->xe + 1}, {"latitude", p->yb, p->ye - p->yb + 1}, {"time", i, 1})
: f.V<DataType>(name, {"longitude", 0, p->xe + 1}, {"latitude", p->yb, p->ye - p->yb + 1}, {"time", i, 1}, {"depth", p->layer, 1});
if(!(var1 && var2)) return Data();
if((var1.DimLen(0) + var2.DimLen(0)) != data.Nx() || var1.DimLen(1) != data.Ny() || var2.DimLen(1) != data.Ny()) return Data();
for(size_t ix = 0; ix < var1.DimLen(0); ix++)
@ -132,12 +143,24 @@ class NEMOData
return data;
}
static MString VName2IName(const MString& vname)
{
if(vname == "temp") return "thetao";
if(vname == "sal") return "so";
if(vname == "mld") return "mlotst";
if(vname == "ssh") return "zos";
if(vname == "w") return "wo";
return "";
}
public:
Data ReadVar(const MString& name, size_t i) const
Data Read(const BaseParameters* ip, size_t i) const
{
if(!isOk()) return Data();
bool nodepth = false;
auto p = dynamic_cast<const struct Parameters*>(ip);
MString name = VName2IName(p->varname);
for(const auto& f: nc)
{
auto head = f.Header();
@ -145,88 +168,84 @@ class NEMOData
if(v.Name() == name)
{
if(v.Dimensions().size() == 3) nodepth = true;
if(v.Type().Id() == NC_SHORT) return ReadVarRaw<int2>(f, name, i, nodepth);
if(v.Type().Id() == NC_FLOAT) return ReadVarRaw<float>(f, name, i, nodepth);
if(v.Type().Id() == NC_SHORT) return ReadVarRaw<int2>(f, name, i, nodepth, p);
if(v.Type().Id() == NC_FLOAT) return ReadVarRaw<float>(f, name, i, nodepth, p);
}
}
return Data();
}
Data ReadVar(const MString& name, const std::vector<size_t>& tindex) const
bool HasVar(const MString vname) const
{
Averager<Data> out;
if(tindex.size() == 0 || !isOk()) return out;
MString name = VName2IName(vname);
if(name == "") return false;
for(size_t i = 0; i < tindex.size(); i++)
for(const auto& f: nc)
{
Data dat = ReadVar(name, tindex[i]);
if(!dat) return Data();
out.Add(dat);
auto head = f.Header();
for(const auto& v: head.Variables())
if(v.Name() == name) return true;
}
out.Div();
return out;
return false;
}
public:
NEMOData() = default;
// TODO: RetVal
bool Open(const MString& stype, const MString& cred, const MString& proxyurl = "")
MString Open(const CLArgs& args)
{
MString oldprefix = GPL.UsePrefix("AVISO");
MString dataset = args.contains("dataset") ? args.at("dataset") : "DT";
MString cred = GPL.ParameterSValue("COPERNICUS_USER", "");
MString proxyurl = GPL.ParameterSValue("COPERNICUS_PROXY", "");
GPL.UsePrefix(oldprefix);
nc.clear();
if(proxyurl.Exist()) proxy.Activate("all_proxy", proxyurl);
if(stype == "DT")
std::vector<MString> urls;
if(dataset == "DT")
{
NCFileA newnc;
newnc.Reset("https://" + cred + "@my.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy_my_0.083_P1D-m");
if(!newnc) return false;
nc.push_back(std::move(newnc));
urls = {"https://" + cred + "@my.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy_my_0.083_P1D-m"};
type = TYPE_DT;
}
if(stype == "NRT")
else if(dataset == "NRT")
{
std::vector<MString> urls{"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-cur_anfc_0.083deg_P1D-m",
"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-thetao_anfc_0.083deg_P1D-m",
"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-so_anfc_0.083deg_P1D-m",
"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy_anfc_0.083deg_P1D-m",
"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-wcur_anfc_0.083deg_P1D-m"};
for(const auto& url: urls)
{
NCFileA newnc;
newnc.Reset(url);
if(!newnc)
{
nc.clear();
return false;
}
nc.push_back(std::move(newnc));
}
urls = {"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-cur_anfc_0.083deg_P1D-m",
"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-thetao_anfc_0.083deg_P1D-m",
"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-so_anfc_0.083deg_P1D-m",
"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy_anfc_0.083deg_P1D-m",
"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-wcur_anfc_0.083deg_P1D-m"};
type = TYPE_NRT;
}
if(stype == "NRT6")
else if(dataset == "NRT6")
{
std::vector<MString> urls{"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-cur_anfc_0.083deg_PT6H-i",
"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-thetao_anfc_0.083deg_PT6H-i",
"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-so_anfc_0.083deg_PT6H-i"};
for(const auto& url: urls)
urls = {"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-cur_anfc_0.083deg_PT6H-i",
"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-thetao_anfc_0.083deg_PT6H-i",
"https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-so_anfc_0.083deg_PT6H-i"};
type = TYPE_NRT6;
}
else
return "Unknown dataset: " + dataset;
nc.resize(urls.size());
for(size_t i = 0; i < urls.size(); i++)
{
nc[i].Reset(urls[i]);
if(!nc[i])
{
NCFileA newnc;
newnc.Reset(url);
if(!newnc)
{
nc.clear();
return false;
}
nc.push_back(std::move(newnc));
nc.clear();
return "Can't connect to database";
}
type = TYPE_NRT6;
}
auto rdepths = nc[0].V<float>("depth");
if(!rdepths)
{
nc.clear();
return false;
return "Can't read depths";
}
depths.resize(rdepths.DimLen(0));
for(size_t i = 0; i < depths.size(); i++) depths[i] = rdepths(i);
@ -236,21 +255,46 @@ class NEMOData
if(!(timeD || timeF))
{
nc.clear();
return false;
return "Can't read times";
}
MDateTime refdate("1950-01-01");
timeD ? times.resize(timeD.DimLen(0)) : times.resize(timeF.DimLen(0));
for(size_t i = 0; i < times.size(); i++) times[i] = refdate + static_cast<time_t>(timeD ? timeD(i) : timeF(i)) * 3600;
return true;
auto nlon = nc[0].D("longitude");
auto nlat = nc[0].D("latitude");
if(!(nlon && nlat))
{
nc.clear();
return "Can't get number of longitudes/latitudes";
}
nx = nlon;
ny = nlat;
auto lons = nc[0].V<float>("longitude");
auto lats = nc[0].V<float>("latitude");
if(!(lons && lats))
{
nc.clear();
return "Can't get longitudes/latitudes";
}
lonb = lons(0);
latb = lats(0);
lone = lons(nx - 1);
late = lats(ny - 1);
lonstep = (lone - lonb) / (nx - 1);
latstep = (late - latb) / (ny - 1);
return "";
}
MString Info() const
{
if(!isOk()) return "";
MString d;
for(size_t i = 0; i < NDepths(); i++) d += MString(" ") + "(" + i + " " + Depth(i) + ")";
std::set<VarType> vars;
std::set<MString> vars;
for(const auto& f: nc)
{
auto head = f.Header();
@ -268,7 +312,7 @@ class NEMOData
bool first = true;
for(const auto& v: vars)
{
svars += (first ? "" : ", ") + v.ShortName();
svars += (first ? "" : ", ") + v;
first = false;
}
}
@ -280,70 +324,81 @@ class NEMOData
" End date: " + Time(NTimes()-1).ToString() + "\n" +
" Time step: " + Timestep() + " seconds\n" +
" Time moments: " + NTimes() + "\n" +
" Region: (" + lonb + " : " + lone + ") x (" + latb + " : " + late + ")\n" +
" Grid: " + nx + "x" + ny + " (" + lonstep + " x " + latstep + ")\n" +
" Depths:" + d + "\n" +
" Supported variables: " + svars;
// clang-format on
}
MString Dump() const
std::pair<const BaseParameters*, MString> Parameters(michlib_internal::ParameterListEx& pars, const CLArgs& args) const
{
// clang-format off
return
"Current settings:\n" + MString() +
" Longitudes: from " + Lonb() + " (" + xb + ") to "+ Lone() + " (" + xe + ")\n" +
" Latitudes: from " + Latb() + " (" + yb + ") to "+ Late() + " (" + ye + ")\n" +
" Depth: layer " + layer + ", depth " + Depth() + " m\n";
// clang-format on
}
std::unique_ptr<struct Parameters> ppar{new struct Parameters};
bool SetRegion(real lonbin, real lonein, real latb, real late, real depth)
{
if(!isOk()) return false;
real lonb = ToGeoDomainNeg(lonbin), lone = ToGeoDomainNeg(lonein);
if(!args.contains("var")) return {nullptr, "Variable not specified"};
ppar->varname = args.at("var");
if(!HasVar(ppar->varname)) return {nullptr, "Variable " + ppar->varname + " not exists in this dataset"};
if(args.contains("layer")) ppar->layer = args.at("layer").ToInteger<size_t>();
if(!args.contains("depth") && ppar->layer >= NDepths()) return {nullptr, MString("Layer ") + ppar->layer + " is too deep!"};
real depth = args.contains("depth") ? args.at("depth").ToReal() : Depth(ppar->layer);
size_t xb_, xe_, yb_, ye_, layer_ = 0;
if(!(args.contains("lonb") && args.contains("lone") && args.contains("latb") && args.contains("late"))) return {nullptr, "Region not specified (lonb, lone, latb, late)"};
yb_ = static_cast<size_t>(Floor((latb + 80.0) * 12.0));
ye_ = static_cast<size_t>(Ceil((late + 80.0) * 12.0));
if(ye_ > 2040) ye_ = 2040;
if(yb_ >= ye_) return false;
{
real lon1 = ToGeoDomainNeg(args.at("lonb").ToReal());
real lon2 = ToGeoDomainNeg(args.at("lone").ToReal());
real lat1 = ToGeoDomainNeg(args.at("latb").ToReal());
real lat2 = ToGeoDomainNeg(args.at("late").ToReal());
xb_ = static_cast<size_t>(Floor((lonb + 180.0) * 12.0));
xe_ = static_cast<size_t>(Ceil((lone + 180.0) * 12.0));
if(xb_ == xe_) return false;
ppar->yb = static_cast<size_t>(Floor((lat1 - latb) / latstep));
ppar->ye = static_cast<size_t>(Ceil((lat2 - latb) / latstep));
if(ppar->ye > 2040) ppar->ye = 2040;
if(ppar->yb >= ppar->ye) return {nullptr, "Latb must be lesser then late"};
if(depth < 0.0 || depth > depths.back())
layer_ = (depth < 0.0) ? 0 : (depths.size() - 1);
else
for(size_t i = 0; i < depths.size() - 1; i++)
{
if(depth >= depths[i] && depth <= depths[i + 1])
ppar->xb = static_cast<size_t>(Floor((lon1 - lonb) / lonstep));
ppar->xe = static_cast<size_t>(Ceil((lon2 - lonb) / lonstep));
if(ppar->xb == ppar->xe) return {nullptr, "Lonb must be not equal late"};
if(depth < 0.0 || depth > depths.back())
ppar->layer = (depth < 0.0) ? 0 : (depths.size() - 1);
else
for(size_t i = 0; i < depths.size() - 1; i++)
{
layer_ = (depth - depths[i] <= depths[i + 1] - depth) ? i : (i + 1);
break;
if(depth >= depths[i] && depth <= depths[i + 1])
{
ppar->layer = (depth - depths[i] <= depths[i + 1] - depth) ? i : (i + 1);
break;
}
}
}
xb = xb_;
xe = xe_;
yb = yb_;
ye = ye_;
layer = layer_;
return true;
}
pars.SetParameter("variable", ppar->varname);
pars.SetParameter("depth", Depth(ppar->layer));
pars.SetParameter("layer", ppar->layer);
pars.SetParameter("dataset", Title());
pars.SetParameter("lonb", Lon(ppar->xb));
pars.SetParameter("latb", Lat(ppar->yb));
pars.SetParameter("lone", Lon(ppar->xe));
pars.SetParameter("late", Lat(ppar->ye));
return {ppar.release(), ""};
}
MString Dump(const struct Parameters* ppar) const
{
// clang-format off
return
"Current settings:\n" + MString() +
" Longitudes: from " + Lon(ppar->xb) + " (" + ppar->xb + ") to "+ Lon(ppar->xe) + " (" + ppar->xe + ")\n" +
" Latitudes: from " + Lat(ppar->yb) + " (" + ppar->yb + ") to "+ Lat(ppar->ye) + " (" + ppar->ye + ")\n" +
" Depth: layer " + ppar->layer + ", depth " + Depth(ppar->layer) + " m\n";
// clang-format on
}
real Lonb() const { return isOk() ? (-180.0 + xb / 12.0) : -1000.0; }
real Lone() const { return isOk() ? (-180.0 + xe / 12.0) : -1000.0; }
real Latb() const { return isOk() ? (-80.0 + yb / 12.0) : -1000.0; }
real Late() const { return isOk() ? (-80.0 + ye / 12.0) : -1000.0; }
size_t Xb() const { return isOk() ? xb : 0; }
size_t Xe() const { return isOk() ? xe : 0; }
size_t Yb() const { return isOk() ? yb : 0; }
size_t Ye() const { return isOk() ? ye : 0; }
size_t Nx() const { return isOk() ? ((xb < xe) ? (xe - xb + 1) : (nx + xe - xb + 1)) : 0; }
size_t Ny() const { return isOk() ? (ye - yb + 1) : 0; }
real Lon(size_t ix) const { return isOk() ? (-180.0 + ix / 12.0) : -1000.0; }
real Lat(size_t iy) const { return isOk() ? (-80.0 + iy / 12.0) : -1000.0; }
real Depth(size_t l) const { return isOk() ? depths[l] : -1000.0; }
real Depth() const { return Depth(layer); }
size_t Layer() const { return layer; }
time_t Timestep() const { return isOk() ? (times[1] - times[0]) : 0; }
MDateTime Time(size_t i) const
{
@ -351,16 +406,12 @@ class NEMOData
return times[i];
}
bool isOk() const { return nc.size() > 0; }
bool isOk() const { return nc.size() > 0; }
explicit operator bool() const { return nc.size() > 0; }
size_t NDepths() const { return depths.size(); }
size_t NTimes() const { return times.size(); }
template<vartype::Vartype vt> Data Read(size_t it) const = delete;
template<vartype::Vartype vt> Data Read(const std::vector<size_t>& tindex) const = delete;
MString Title() const
{
switch(type)
@ -374,19 +425,3 @@ class NEMOData
static real Fillval() { return Data::Fillval(); }
};
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::U>(size_t it) const { return ReadVar("uo", it); }
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::V>(size_t it) const { return ReadVar("vo", it); }
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::TEMP>(size_t it) const { return ReadVar("thetao", it); }
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::SAL>(size_t it) const { return ReadVar("so", it); }
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::MLD>(size_t it) const { return ReadVar("mlotst", it); }
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::SSH>(size_t it) const { return ReadVar("zos", it); }
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::W>(size_t it) const { return ReadVar("wo", it); }
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::U>(const std::vector<size_t>& tindex) const { return ReadVar("uo", tindex); }
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::V>(const std::vector<size_t>& tindex) const { return ReadVar("vo", tindex); }
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::TEMP>(const std::vector<size_t>& tindex) const { return ReadVar("thetao", tindex); }
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::SAL>(const std::vector<size_t>& tindex) const { return ReadVar("so", tindex); }
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::MLD>(const std::vector<size_t>& tindex) const { return ReadVar("mlotst", tindex); }
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::SSH>(const std::vector<size_t>& tindex) const { return ReadVar("zos", tindex); }
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::W>(const std::vector<size_t>& tindex) const { return ReadVar("wo", tindex); }

7
include/ParseArgs.h

@ -0,0 +1,7 @@
#pragma once
#include "GPL.h"
using michlib::MString;
using CLArgs = std::map<MString, MString>;
CLArgs ParseArgs(int argc, char** argv);

24
include/basedata.h

@ -1,25 +1,45 @@
#pragma once
#include "comdefs.h"
#include <vector>
using michlib::real;
class BaseParameters
{
public:
virtual ~BaseParameters();
};
class BaseData
{
protected:
static constexpr real fillval = 1.0e10;
std::vector<real> data;
std::vector<real> lons, lats;
BaseData() = default;
BaseData(size_t n): data(n), lons(n), lats(n) {}
BaseData(size_t n): data(n) {}
template<class Lon, class Lat> BaseData(size_t n, Lon genlon, Lat genlat): data(n), lons(n), lats(n)
{
for(size_t i = 0; i < n; i++)
{
lons[i] = genlon(i);
lats[i] = genlat(i);
}
};
public:
BaseData() = default;
const real& V(size_t i) const { return data[i]; }
real& V(size_t i) { return data[i]; }
const real& operator()(size_t i) const { return data[i]; }
real& operator()(size_t i) { return data[i]; }
real Lon(size_t i) const { return lons[i]; }
real Lat(size_t i) const { return lats[i]; }
size_t N() const { return data.size(); }
static real Fillval() { return fillval; }

180
include/odm.h

@ -1,29 +1,121 @@
#pragma once
#include "BFileW.h"
#include "GPL.h"
#include "NEMO.h"
#include "tindexes.h"
#include <utility>
#include <variant>
using michlib::BFileW;
using michlib::errmessage;
using michlib::GPL;
using michlib::message;
using michlib::SList;
using DataVariants = std::variant<NEMOData>;
using CLArgs = std::map<MString, MString>;
template<class T>
concept InfoSupported = requires(T t) {
{
t.template Info()
} -> std::convertible_to<MString>;
};
template<class T>
concept ParametersSupported = requires(T t, michlib_internal::ParameterListEx& pars, const CLArgs& args) {
{
t.template Parameters(pars, args).first
} -> std::convertible_to<const BaseParameters*>;
};
template<class T>
concept ReadPSupported = requires(T t, const BaseParameters* ip, size_t i) {
{
t.template Read(ip, i)(0)
} -> std::convertible_to<real>;
};
template<class T>
concept ReadSupported = requires(T t, size_t i) {
{
t.template Read(i)(0)
} -> std::convertible_to<real>;
};
template<class T>
concept ActionTscSupported = requires(T t, michlib_internal::ParameterListEx& pars, const CLArgs& args, const BaseParameters* ip, size_t i) {
{
t.template Parameters(pars, args).first
} -> std::convertible_to<const BaseParameters*>;
{
t.template Read(ip, i)(0)
} -> std::convertible_to<real>;
};
class Data: public DataVariants
{
template<class D> static bool WriteData(BFileW& fw, const D& data)
public:
using TIndex = std::vector<size_t>;
private:
TIndex GetTIndexes(const MDateTime& b, const MDateTime& e) const
{
for(size_t i = 0; i < data.N(); i++)
TIndex out;
auto nt = NTimes();
const MDateTime& beg = (b < e) ? b : e;
const MDateTime& end = (b > e) ? b : e;
if(beg > Time(nt - 1) || end < Time(0)) return out;
size_t ib = 0, ie = nt - 1;
for(size_t i = 0; i < nt; i++)
if(Time(i) >= beg)
{
ib = i;
break;
}
for(size_t i = nt; i != 0; i--)
if(Time(i - 1) <= end)
{
ie = i - 1;
break;
}
out.resize(ie - ib + 1);
for(size_t i = 0; i < ie - ib + 1; i++) out[i] = i + ib;
return out;
}
TIndex GetTIndexes(const MString& regex)
{
{
MDateTime time;
if(time.FromString(regex)) return TIndex(1, GetTIndex(time)); // Time, not regex
if(regex == "BEGIN" || regex == "BEG" || regex == "FIRST") return TIndex(1, 0); // First time
if(regex == "END" || regex == "LAST") return TIndex(1, NTimes() - 1); // Last time
}
TIndex out;
std::unique_ptr<regex_t> regbuf(new regex_t);
if(0 != regcomp(regbuf.get(), regex.Buf(), REG_EXTENDED | REG_NOSUB)) return out;
for(size_t i = 0; i < NTimes(); i++)
{
fw.Write(data.Lon(i));
fw.Write(data.Lat(i));
fw.Write(data(i) == data.Fillval() ? NAN : data(i));
MString date = Time(i).ToString();
if(0 != regexec(regbuf.get(), date.Buf(), 0, 0, 0)) continue;
out.push_back(i);
}
return true;
return out;
}
size_t GetTIndex(const MDateTime& t)
{
size_t nt = NTimes();
if(t <= Time(0)) return 0;
if(t >= Time(nt - 1)) return nt - 1;
for(size_t i = 0; i < nt - 1; i++)
if(t >= Time(i) && t <= Time(i + 1)) return (t - Time(i) <= Time(i + 1) - t) ? i : (i + 1);
return 0;
}
public:
@ -31,59 +123,31 @@ class Data: public DataVariants
Data(DataVariants&& d): DataVariants(std::move(d)) {}
auto Time(size_t it) const
MDateTime Time(size_t it) const
{
return std::visit(
[it = it](const auto& arg) -> auto{ return arg.Time(it); }, *this);
return std::visit([it = it](const auto& arg) -> auto { return arg.Time(it); }, *this);
}
auto NTimes() const
size_t NTimes() const
{
return std::visit(
[](const auto& arg) -> auto{ return arg.NTimes(); }, *this);
}
auto Info() const
{
return std::visit(
[](const auto& arg) -> auto{ return arg.Info(); }, *this);
return std::visit([](const auto& arg) -> auto { return arg.NTimes(); }, *this);
}
bool Write(BFileW& fw, VarType vt, const std::vector<size_t>& tindexes) const
MString Init(const CLArgs& args)
{
return std::visit(
[&fw = fw, vt = vt, &ti = tindexes](const auto& d) -> bool
{
using T = std::decay_t<decltype(d)>;
return std::visit(
[&fw = fw, &ti = ti, &d = d](auto v) -> bool
{
constexpr auto cvt = decltype(v)::vt;
if constexpr(isDataSupported<T, cvt>)
return WriteData(fw, d.template Read<cvt>(ti));
else
return false;
},
vt);
},
*this);
MString src = args.contains("source") ? args.at("source") : "";
if(!src.Exist()) return "No source specified";
if(src == "NEMO")
{
NEMOData data;
auto res = data.Open(args);
if(res.Exist()) return "Can't open source " + src + ":\n" + res;
*this = Data(std::move(data));
}
else
return "Unknown source: " + src;
return "";
}
};
CLArgs ParseArgs(int argc, char** argv);
int actioninfo(const CLArgs& args);
int actiontsc(const CLArgs& args);
inline NEMOData NEMOOpen(const CLArgs& args)
{
NEMOData ndata;
MString oldprefix = GPL.UsePrefix("AVISO");
MString dataset = args.contains("dataset") ? args.at("dataset") : "DT";
MString cred = GPL.ParameterSValue("COPERNICUS_USER", "");
MString proxy = GPL.ParameterSValue("COPERNICUS_PROXY", "");
GPL.UsePrefix(oldprefix);
ndata.Open(dataset, cred, proxy);
return ndata;
}
MString ActionInfo(const CLArgs& args);
MString ActionTsc(const CLArgs& args);
};

13
include/simple2ddata.h

@ -10,7 +10,18 @@ class Simple2DData: public BaseData
public:
Simple2DData() = default;
Simple2DData(size_t nx_, size_t ny_, real x0_, real y0_, real xs_, real ys_): BaseData(nx_ * ny_), x0(x0_), y0(y0_), nx(nx_), ny(ny_), xstep(xs_), ystep(ys_) {}
Simple2DData(size_t nx_, size_t ny_, real x0_, real y0_, real xs_, real ys_):
BaseData(
nx_ * ny_, [x0 = x0_, nx = nx_, xstep = xs_](size_t i) -> real { return x0 + (i % nx) * xstep; },
[y0 = y0_, nx = nx_, ystep = ys_](size_t i) -> real { return y0 + (i / nx) * ystep; }),
x0(x0_),
y0(y0_),
nx(nx_),
ny(ny_),
xstep(xs_),
ystep(ys_)
{
}
const real& V(size_t i) const { return BaseData::V(i); }
real& V(size_t i) { return BaseData::V(i); }

63
include/tindexes.h

@ -1,63 +0,0 @@
#pragma once
#include "mdatetime.h"
#include <memory>
#include <vector>
using michlib::MDateTime;
template<class T> std::vector<size_t> GetTIndexes(const T& adapter, const MDateTime& b, const MDateTime& e)
{
std::vector<size_t> out;
auto nt = adapter.NTimes();
const MDateTime& beg = (b < e) ? b : e;
const MDateTime& end = (b > e) ? b : e;
if(beg > adapter.Time(nt - 1) || end < adapter.Time(0)) return out;
size_t ib = 0, ie = nt - 1;
for(size_t i = 0; i < nt; i++)
if(adapter.Time(i) >= beg)
{
ib = i;
break;
}
for(size_t i = nt; i != 0; i--)
if(adapter.Time(i - 1) <= end)
{
ie = i - 1;
break;
}
out.resize(ie - ib + 1);
for(size_t i = 0; i < ie - ib + 1; i++) out[i] = i + ib;
return out;
}
template<class T> std::vector<size_t> GetTIndexes(const T& adapter, const MString& regex)
{
std::vector<size_t> out;
std::unique_ptr<regex_t> regbuf(new regex_t);
if(0 != regcomp(regbuf.get(), regex.Buf(), REG_EXTENDED | REG_NOSUB)) return out;
for(size_t i = 0; i < adapter.NTimes(); i++)
{
MString date = adapter.Time(i).ToString();
if(0 != regexec(regbuf.get(), date.Buf(), 0, 0, 0)) continue;
out.push_back(i);
}
return out;
}
template<class T> size_t GetTIndex(const T& adapter, const MDateTime& t)
{
size_t nt = adapter.NTimes();
if(t <= adapter.Time(0)) return 0;
if(t >= adapter.Time(nt - 1)) return nt - 1;
for(size_t i = 0; i < nt - 1; i++)
if(t >= adapter.Time(i) && t <= adapter.Time(i + 1)) return (t - adapter.Time(i) <= adapter.Time(i + 1) - t) ? i : (i + 1);
return 0;
}

118
include/vartype.h

@ -1,118 +0,0 @@
#pragma once
#include "MString.h"
#include <variant>
using michlib::MString;
namespace vartype
{
enum class Vartype
{
NONE,
U,
V,
TEMP,
SAL,
CHL,
MLD,
SSH,
W
};
template<Vartype vt_> struct VartypeCarrier
{
static const Vartype vt = vt_;
};
using VartypeUnion =
std::variant<VartypeCarrier<Vartype::NONE>, VartypeCarrier<Vartype::U>, VartypeCarrier<Vartype::V>, VartypeCarrier<Vartype::TEMP>, VartypeCarrier<Vartype::SAL>,
VartypeCarrier<Vartype::CHL>, VartypeCarrier<Vartype::MLD>, VartypeCarrier<Vartype::SSH>, VartypeCarrier<Vartype::W>>;
template<class T, Vartype vt>
concept HasVar = requires(T t) {
{
t.template Read<vt>(0)(0, 0)
} -> std::convertible_to<real>;
{
t.template Read<vt>(std::vector<size_t>())(0, 0)
} -> std::convertible_to<real>;
};
} // namespace vartype
template<class DT, vartype::Vartype vt> static constexpr bool isDataSupported = vartype::HasVar<DT, vt>;
class VarType: public vartype::VartypeUnion
{
auto VT() const
{
return std::visit(
[](auto v) -> auto{ return decltype(v)::vt; }, *this);
}
public:
template<vartype::Vartype vt> VarType(vartype::VartypeCarrier<vt>&& vc): vartype::VartypeUnion(std::move(vc)) {}
VarType(MString str)
{
str.ToLower();
if(str == "u") *this = vartype::VartypeCarrier<vartype::Vartype::U>();
if(str == "v") *this = vartype::VartypeCarrier<vartype::Vartype::V>();
if(str == "t" || str == "temp" || str == "temperature") *this = vartype::VartypeCarrier<vartype::Vartype::TEMP>();
if(str == "s" || str == "sal" || str == "salinity") *this = vartype::VartypeCarrier<vartype::Vartype::SAL>();
if(str == "c" || str == "chl" || str == "chlorophyll") *this = vartype::VartypeCarrier<vartype::Vartype::CHL>();
if(str == "mld") *this = vartype::VartypeCarrier<vartype::Vartype::MLD>();
if(str == "ssh") *this = vartype::VartypeCarrier<vartype::Vartype::SSH>();
if(str == "w") *this = vartype::VartypeCarrier<vartype::Vartype::W>();
}
MString Name() const
{
switch(VT())
{
case(vartype::Vartype::NONE): return "none";
case(vartype::Vartype::U): return "U";
case(vartype::Vartype::V): return "V";
case(vartype::Vartype::TEMP): return "Temperature";
case(vartype::Vartype::SAL): return "Salinity";
case(vartype::Vartype::CHL): return "Chlorophyll";
case(vartype::Vartype::MLD): return "Mixed layer depth";
case(vartype::Vartype::SSH): return "Sea surface height";
case(vartype::Vartype::W): return "W";
}
return "none";
}
MString ShortName() const
{
switch(VT())
{
case(vartype::Vartype::NONE): return "none";
case(vartype::Vartype::U): return "u";
case(vartype::Vartype::V): return "v";
case(vartype::Vartype::TEMP): return "temp";
case(vartype::Vartype::SAL): return "sal";
case(vartype::Vartype::CHL): return "chl";
case(vartype::Vartype::MLD): return "mld";
case(vartype::Vartype::SSH): return "ssh";
case(vartype::Vartype::W): return "w";
}
return "none";
}
bool Ok() const { return VT() != vartype::Vartype::NONE; }
explicit operator bool() const { return Ok(); }
bool operator==(const VarType& vt) const { return VT() == vt.VT(); }
auto operator<=>(const VarType& vt) const { return VT() <=> vt.VT(); }
template<class Data> bool isSupported() const
{
return std::visit(
[](const auto v) -> bool
{
if constexpr(isDataSupported<Data, decltype(v)::vt>)
return true;
else
return false;
},
*this);
}
};

5
src/ParseArgs.cpp

@ -1,6 +1,7 @@
#define MICHLIB_NOSOURCE
#include "GPL.h"
#include "odm.h"
#include "ParseArgs.h"
using michlib::SList;
CLArgs ParseArgs(int argc, char** argv)
{

45
src/actioninfo.cpp

@ -1,36 +1,19 @@
#define MICHLIB_NOSOURCE
#include "GPL.h"
#include "odm.h"
int actioninfo(const CLArgs& args)
MString Data::ActionInfo(const CLArgs& args)
{
if(!args.contains("source"))
{
errmessage("No source specified!");
return 1;
}
Data data;
if(args.at("source") == "NEMO")
{
NEMOData ndata = NEMOOpen(args);
if(!ndata)
{
errmessage("Can't open NEMO dataset");
return 1;
}
data = DataVariants(std::move(ndata));
}
else
{
errmessage("Unknown source " + args.at("source"));
return 1;
}
message(data.Info());
return 0;
MString info = std::visit(
[](const auto& arg) -> auto
{
using T = std::decay_t<decltype(arg)>;
if constexpr(InfoSupported<T>)
return arg.Info();
else
return MString();
},
*this);
if(!info.Exist()) return "Unsupported combination of action and source";
message(info);
return "";
}

165
src/actiontsc.cpp

@ -2,132 +2,97 @@
#include "GPL.h"
#include "odm.h"
int actiontsc(const CLArgs& args)
MString Data::ActionTsc(const CLArgs& args)
{
if(!args.contains("source"))
{
errmessage("No source specified!");
return 1;
}
VarType vtype(args.at("var"));
if(!vtype)
{
errmessage("Incorrect or no variable specified");
return 1;
}
if(args.contains("time") && (args.contains("timeb") || args.contains("timee"))) return "Time must be set via time parameter or timeb and timee parameter but not via both";
if(!(args.contains("time") || (args.contains("timeb") && args.contains("timee")))) return "Time must be set via time parameter or timeb and timee parameter";
michlib_internal::ParameterListEx pars;
pars.UsePrefix("");
pars.SetParameter("source", args.at("source"));
pars.SetParameter("variable", vtype.Name());
TIndex tindexes;
Data data;
if(args.at("source") == "NEMO")
if(args.contains("time"))
{
if(!vtype.isSupported<NEMOData>())
{
errmessage("Variable " + args.at("var") + " is unsupported by NEMO");
return 1;
}
NEMOData ndata = NEMOOpen(args);
if(!ndata)
{
errmessage("Can't open NEMO dataset");
return 1;
}
size_t layer = 0;
if(args.contains("layer")) layer = args.at("layer").ToInteger<size_t>();
if(!args.contains("depth") && layer >= ndata.NDepths())
{
errmessage(MString("Layer ") + layer + " is too deep!");
return 1;
}
real depth = args.contains("depth") ? args.at("depth").ToReal() : ndata.Depth(layer);
if(!(args.contains("lonb") && args.contains("lone") && args.contains("latb") && args.contains("late")))
{
errmessage("Region not specified (lonb, lone, latb, late)");
return 1;
}
if(!ndata.SetRegion(args.at("lonb").ToReal(), args.at("lone").ToReal(), args.at("latb").ToReal(), args.at("late").ToReal(), depth))
{
errmessage("Can't set region");
return 1;
}
pars.SetParameter("depth", depth);
pars.SetParameter("layer", ndata.Layer());
pars.SetParameter("dataset", ndata.Title());
pars.SetParameter("lonb", args.at("lonb").ToReal());
pars.SetParameter("latb", args.at("latb").ToReal());
pars.SetParameter("lone", args.at("lone").ToReal());
pars.SetParameter("late", args.at("late").ToReal());
data = DataVariants(std::move(ndata));
tindexes = GetTIndexes(args.at("time")); // Regular expression or single date
if(tindexes.size() == 0) return "There are no times matching the regular expression";
if(tindexes.size() == 1)
pars.SetParameter("time", Time(tindexes[0]).ToString());
else
pars.SetParameter("timeregex", args.at("time"));
}
else
{
errmessage("Unknown source " + args.at("source"));
return 1;
MDateTime tb(args.at("timeb")), te(args.at("timee"));
tindexes = GetTIndexes(tb, te);
if(tindexes.size() == 0) return "There are no times between " + tb.ToString() + " and " + te.ToString();
pars.SetParameter("timeb", tb.ToString());
pars.SetParameter("timee", te.ToString());
}
if(args.contains("time") && (args.contains("timeb") || args.contains("timee")))
std::unique_ptr<const BaseParameters> sourcepars;
{
errmessage("Time must be set via time parameter or timeb and timee parameter but not via both");
return 1;
std::pair<const BaseParameters*, MString> ppar = std::visit(
[&pars = pars, &args = args](const auto& arg) -> std::pair<const BaseParameters*, MString>
{
using T = std::decay_t<decltype(arg)>;
if constexpr(ParametersSupported<T>)
return arg.Parameters(pars, args);
else
return {nullptr, ""};
},
*this);
if(ppar.second.Exist()) return ppar.second;
sourcepars.reset(ppar.first);
}
if(!(args.contains("time") || (args.contains("timeb") && args.contains("timee"))))
auto p = sourcepars.get();
size_t ind;
auto read = [p = p, &ind = ind](const auto& arg) -> BaseData
{
using T = std::decay_t<decltype(arg)>;
if constexpr(ParametersSupported<T> && ReadPSupported<T>)
return arg.Read(p, ind);
else if constexpr(!ParametersSupported<T> && ReadSupported<T>)
return arg.Read(ind);
else
return BaseData();
};
BaseData data;
if(tindexes.size() == 1)
data = std::visit(read, *this);
else
{
errmessage("Time must be set via time parameter or timeb and timee parameter");
return 1;
Averager<BaseData> out;
bool ok = true;
for(size_t i = 0; i < tindexes.size(); i++)
{
if(!ok) break;
ind = tindexes[i];
auto dat = std::visit(read, *this);
if(dat)
out.Add(dat);
else
ok = false;
}
if(ok) data = out.Div();
}
if(!data) return "Can't read data";
BFileW fw;
MString name = args.contains("out") ? args.at("out") : "";
if(!name.Exist()) name = "out.bin";
fw.Create(name, 3);
/*
if(!fw.Create(name,3))
{
errmessage("Can't create file "+name);
return 1;
}
*/
fw.SetParameters(pars);
fw.UsePrefix("");
if(args.contains("time"))
for(size_t i = 0; i < data.N(); i++)
{
MDateTime time;
if(time.FromString(args.at("time"))) // One date
{
auto it = GetTIndex(data, time);
fw.SetParameter("time", data.Time(it).ToString());
data.Write(fw, vtype, std::vector<size_t>(1, it));
}
else // Regular expression
{
fw.SetParameter("timeregex", args.at("time"));
data.Write(fw, vtype, GetTIndexes(data, args.at("time")));
}
fw.Write(data.Lon(i));
fw.Write(data.Lat(i));
fw.Write(data(i) == data.Fillval() ? NAN : data(i));
}
else // Bdate, edate
{
MDateTime tb(args.at("timeb")), te(args.at("timee"));
fw.SetParameter("timeb", tb.ToString());
fw.SetParameter("timee", te.ToString());
data.Write(fw, vtype, GetTIndexes(data, tb, te));
}
fw.Finalize();
fw.Close();
return 0;
return "";
}

3
src/basedata.cpp

@ -0,0 +1,3 @@
#include "basedata.h"
BaseParameters::~BaseParameters() {}

23
src/odm.cpp

@ -33,16 +33,31 @@ int main(int argc, char** argv)
MString action = args.contains("action") ? args["action"] : "tsc";
int ret = 1;
Data data;
{
auto ret = data.Init(args);
if(ret.Exist())
{
errmessage(ret);
return 1;
}
}
MString ret;
if(action == "info")
ret = actioninfo(args);
ret = data.ActionInfo(args);
else if(action == "tsc")
ret = actiontsc(args);
ret = data.ActionTsc(args);
else
{
errmessage("Unknown action " + action);
return 1;
}
if(ret.Exist())
{
errmessage(ret);
return 1;
}
return ret;
return 0;
}

Loading…
Cancel
Save