Browse Source

The data source classes get the region from outside rather than reading it themselves from the parameters.

interpolate
Michael Uleysky 11 months ago
parent
commit
0213249f78
  1. 18
      actions/actiongenintfile.h
  2. 18
      actions/actiontsc.h
  3. 18
      actions/actionuv.h
  4. 200
      include/actiondep.h
  5. 185
      include/actions.h
  6. 5
      include/basedata.h
  7. 2
      include/layereddata.h
  8. 12
      include/traits.h
  9. 11
      sources/AVISOLOCAL.cpp
  10. 2
      sources/AVISOLOCAL.h
  11. 12
      sources/MODISBINLOCAL.cpp
  12. 2
      sources/MODISBINLOCAL.h
  13. 12
      src/layereddata.cpp

18
actions/actiongenintfile.h

@ -11,6 +11,9 @@ ADD_ACTION(GenIntFile, genintfile, ReadIsGrid<Source>);
template<class D> MString ActionGenIntFile::DoAction(const CLArgs& args, D& ds)
{
auto [reg, regerr] = GetRegion<D>(args);
if(regerr.Exist()) return regerr;
auto resop = ds.Open(args);
if(resop.Exist()) return "Can't open source: " + resop;
@ -30,9 +33,18 @@ template<class D> MString ActionGenIntFile::DoAction(const CLArgs& args, D& ds)
std::unique_ptr<const BaseParameters> sourcepars;
if constexpr(ParametersSupported<D>)
{
auto [p, err] = ds.Parameters(pars, args);
if(err.Exist()) return err;
sourcepars.reset(p);
if constexpr(ParametersRequiredRegion<D>)
{
auto [p, err] = ds.Parameters(pars, args, reg);
if(err.Exist()) return err;
sourcepars.reset(p);
}
else
{
auto [p, err] = ds.Parameters(pars, args);
if(err.Exist()) return err;
sourcepars.reset(p);
}
}
auto p = sourcepars.get();

18
actions/actiontsc.h

@ -9,6 +9,9 @@ ADD_ACTION(TSC, tsc, ReadPSupported<Source> || ReadSupported<Source>);
template<class D> MString ActionTSC::DoAction(const CLArgs& args, D& ds)
{
auto [reg, regerr] = GetRegion<D>(args);
if(regerr.Exist()) return regerr;
auto resop = ds.Open(args);
if(resop.Exist()) return "Can't open source: " + resop;
@ -27,9 +30,18 @@ template<class D> MString ActionTSC::DoAction(const CLArgs& args, D& ds)
std::unique_ptr<const BaseParameters> sourcepars;
if constexpr(ParametersSupported<D>)
{
auto [p, err] = ds.Parameters(pars, args);
if(err.Exist()) return err;
sourcepars.reset(p);
if constexpr(ParametersRequiredRegion<D>)
{
auto [p, err] = ds.Parameters(pars, args, reg);
if(err.Exist()) return err;
sourcepars.reset(p);
}
else
{
auto [p, err] = ds.Parameters(pars, args);
if(err.Exist()) return err;
sourcepars.reset(p);
}
}
auto p = sourcepars.get();

18
actions/actionuv.h

@ -9,6 +9,9 @@ ADD_ACTION(UV, uv, ReadPSupported<Source> || ReadSupported<Source>);
template<class D> MString ActionUV::DoAction(const CLArgs& args, D& ds)
{
auto [reg, regerr] = GetRegion<D>(args);
if(regerr.Exist()) return regerr;
auto resop = ds.Open(args);
if(resop.Exist()) return "Can't open source: " + resop;
@ -22,9 +25,18 @@ template<class D> MString ActionUV::DoAction(const CLArgs& args, D& ds)
std::unique_ptr<const BaseParameters> sourcepars;
if constexpr(ParametersSupported<D>)
{
auto [p, err] = ds.Parameters(pars, args);
if(err.Exist()) return err;
sourcepars.reset(p);
if constexpr(ParametersRequiredRegion<D>)
{
auto [p, err] = ds.Parameters(pars, args, reg);
if(err.Exist()) return err;
sourcepars.reset(p);
}
else
{
auto [p, err] = ds.Parameters(pars, args);
if(err.Exist()) return err;
sourcepars.reset(p);
}
}
auto p = sourcepars.get();

200
include/actiondep.h

@ -1,6 +1,12 @@
#pragma once
#include "ParseArgs.h"
#include "basedata.h"
#include "mdatetime.h"
#include "mregex.h"
#include "traits.h"
#include "uvdata.h"
using michlib::MDateTime;
#if defined GENACTIONLIST
#define ADD_ACTION(actclass, actname, suptest) ADD ACTION CLASS: actclass
@ -14,3 +20,197 @@
template<class Source> static MString DoAction(const CLArgs& args, Source& data); \
};
#endif
template<class D> size_t GetTIndex(const D& data, const MDateTime& t)
{
size_t nt = data.NTimes();
if(t <= data.Time(0)) return 0;
if(t >= data.Time(nt - 1)) return nt - 1;
for(size_t i = 0; i < nt - 1; i++)
if(t >= data.Time(i) && t <= data.Time(i + 1)) return (t - data.Time(i) <= data.Time(i + 1) - t) ? i : (i + 1);
return 0;
}
template<class D> std::pair<TIndex, MString> GetTIndexes(const D& data, const CLArgs& args, michlib_internal::ParameterListEx& pars)
{
TIndex tindexes;
if(args.contains("time") && (args.contains("timeb") || args.contains("timee")))
return {tindexes, "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 {tindexes, "Time must be set via time parameter or timeb and timee parameter"};
if(args.contains("time"))
{
MString regex = args.at("time");
MDateTime time;
if(time.FromString(regex)) return {TIndex(1, GetTIndex(data, 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, data.NTimes() - 1), ""}; // Last time
michlib::RegExpSimple reg(regex.Buf());
if(reg.Compile() != 0) return {tindexes, "Bad regular expression: " + regex};
for(size_t i = 0; i < data.NTimes(); i++)
{
MString date = data.Time(i).ToString();
if(reg.Match(date.Buf())) tindexes.push_back(i);
}
if(tindexes.size() == 0) return {tindexes, "There are no times matching the regular expression: " + regex};
if(tindexes.size() == 1)
pars.SetParameter("time", data.Time(tindexes[0]).ToString());
else
pars.SetParameter("timeregex", args.at("time"));
}
else
{
MString tb = args.at("timeb");
MString te = args.at("timee");
MDateTime b(tb), e(te);
auto nt = data.NTimes();
if(tb == "BEGIN" || tb == "BEG") b = data.Time(0);
if(te == "LAST" || te == "END") e = data.Time(nt - 1);
const MDateTime& beg = (b < e) ? b : e;
const MDateTime& end = (b > e) ? b : e;
if(beg > data.Time(nt - 1)) return {tindexes, "Begin time " + b.ToTString() + " is greater then end time in the dataset " + data.Time(nt - 1).ToTString()};
if(end < data.Time(0)) return {tindexes, "End time " + e.ToTString() + " is lesser then begin time in the dataset " + data.Time(0).ToTString()};
size_t ib = 0, ie = nt - 1;
for(size_t i = 0; i < nt; i++)
if(data.Time(i) >= beg)
{
ib = i;
break;
}
for(size_t i = nt; i != 0; i--)
if(data.Time(i - 1) <= end)
{
ie = i - 1;
break;
}
tindexes.resize(ie - ib + 1);
for(size_t i = 0; i < ie - ib + 1; i++) tindexes[i] = i + ib;
if(tindexes.size() == 0) return {tindexes, "There are no times between " + b.ToString() + " and " + e.ToString()};
pars.SetParameter("timeb", b.ToString());
pars.SetParameter("timee", e.ToString());
}
return {tindexes, ""};
}
template<class D> ReadType<D> Read(const D& data, const MString& vname, const BaseParameters* p, const TIndex& tindex)
{
using RT = ReadType<D>;
size_t ind;
if(tindex.size() == 1)
{
ind = tindex[0];
michlib::message("Time: " + data.Time(ind).ToTString());
if constexpr(ReadPSupported<D>)
return data.Read(vname, p, ind);
else if constexpr(ReadSupported<D>)
return data.Read(vname, ind);
}
else
{
Averager<RT> out;
bool ok = true;
for(size_t i = 0; i < tindex.size(); i++)
{
if(!ok) break;
ind = tindex[i];
michlib::message("Time: " + data.Time(ind).ToTString());
RT dat;
if constexpr(ReadPSupported<D>)
dat = data.Read(vname, p, ind);
else if constexpr(ReadSupported<D>)
dat = data.Read(vname, ind);
if(dat)
out.Add(dat);
else
ok = false;
}
if(ok) return out.Div();
}
return RT();
}
template<class D> UVData<ReadType<D>> ReadUV(const D& data, const BaseParameters* p, size_t ind)
{
using RT = ReadType<D>;
using UV = UVData<RT>;
michlib::message("Time: " + data.Time(ind).ToTString());
RT u, v;
if constexpr(ReadPSupported<D>)
{
u = data.Read("u", p, ind);
v = data.Read("v", p, ind);
}
else if constexpr(ReadSupported<D>)
{
u = data.Read("u", ind);
v = data.Read("v", ind);
}
return UV(u, v);
}
template<class D> UVData<ReadType<D>> ReadUV(const D& data, const BaseParameters* p, const TIndex& tindex)
{
using RT = ReadType<D>;
using UV = UVData<RT>;
if(tindex.size() == 1)
return ReadUV(data, p, tindex[0]);
else
{
Averager<UV> out;
bool ok = true;
size_t ind;
for(size_t i = 0; i < tindex.size(); i++)
{
if(!ok) break;
ind = tindex[i];
michlib::message("Time: " + data.Time(ind).ToTString());
RT u, v;
if constexpr(ReadPSupported<D>)
{
u = data.Read("u", p, ind);
v = data.Read("v", p, ind);
}
else if constexpr(ReadSupported<D>)
{
u = data.Read("u", ind);
v = data.Read("v", ind);
}
UV dat(u, v);
if(dat)
out.Add(dat);
else
ok = false;
}
if(ok) return out.Div();
}
return UV();
}
template<class D> std::pair<struct Region, MString> GetRegion(const CLArgs& args)
{
struct Region reg;
if constexpr(!ParametersRequiredRegion<D>) return {reg, ""};
if(!(args.contains("lonb") && args.contains("lone") && args.contains("latb") && args.contains("late"))) return {reg, "Region not specified (lonb, lone, latb, late)"};
reg.lonb = args.at("lonb").ToReal();
reg.lone = args.at("lone").ToReal();
real latb = args.at("latb").ToReal();
real late = args.at("late").ToReal();
reg.latb = std::min(latb, late);
reg.late = std::max(latb, late);
return {reg, ""};
}

185
include/actions.h

@ -1,13 +1,7 @@
#pragma once
#include "actionlist.h"
#include "basedata.h"
#include "mdatetime.h"
#include "mregex.h"
#include "uvdata.h"
#include "varhelpers.h"
using michlib::MDateTime;
using ActionVariants = std::variant<ACTLIST>;
class Action: public ActionVariants
@ -23,182 +17,3 @@ class Action: public ActionVariants
return "";
}
};
template<class D> size_t GetTIndex(const D& data, const MDateTime& t)
{
size_t nt = data.NTimes();
if(t <= data.Time(0)) return 0;
if(t >= data.Time(nt - 1)) return nt - 1;
for(size_t i = 0; i < nt - 1; i++)
if(t >= data.Time(i) && t <= data.Time(i + 1)) return (t - data.Time(i) <= data.Time(i + 1) - t) ? i : (i + 1);
return 0;
}
template<class D> std::pair<TIndex, MString> GetTIndexes(const D& data, const CLArgs& args, michlib_internal::ParameterListEx& pars)
{
TIndex tindexes;
if(args.contains("time") && (args.contains("timeb") || args.contains("timee")))
return {tindexes, "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 {tindexes, "Time must be set via time parameter or timeb and timee parameter"};
if(args.contains("time"))
{
MString regex = args.at("time");
MDateTime time;
if(time.FromString(regex)) return {TIndex(1, GetTIndex(data, 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, data.NTimes() - 1), ""}; // Last time
michlib::RegExpSimple reg(regex.Buf());
if(reg.Compile() != 0) return {tindexes, "Bad regular expression: " + regex};
for(size_t i = 0; i < data.NTimes(); i++)
{
MString date = data.Time(i).ToString();
if(reg.Match(date.Buf())) tindexes.push_back(i);
}
if(tindexes.size() == 0) return {tindexes, "There are no times matching the regular expression: " + regex};
if(tindexes.size() == 1)
pars.SetParameter("time", data.Time(tindexes[0]).ToString());
else
pars.SetParameter("timeregex", args.at("time"));
}
else
{
MString tb = args.at("timeb");
MString te = args.at("timee");
MDateTime b(tb), e(te);
auto nt = data.NTimes();
if(tb == "BEGIN" || tb == "BEG") b = data.Time(0);
if(te == "LAST" || te == "END") e = data.Time(nt - 1);
const MDateTime& beg = (b < e) ? b : e;
const MDateTime& end = (b > e) ? b : e;
if(beg > data.Time(nt - 1)) return {tindexes, "Begin time " + b.ToTString() + " is greater then end time in the dataset " + data.Time(nt - 1).ToTString()};
if(end < data.Time(0)) return {tindexes, "End time " + e.ToTString() + " is lesser then begin time in the dataset " + data.Time(0).ToTString()};
size_t ib = 0, ie = nt - 1;
for(size_t i = 0; i < nt; i++)
if(data.Time(i) >= beg)
{
ib = i;
break;
}
for(size_t i = nt; i != 0; i--)
if(data.Time(i - 1) <= end)
{
ie = i - 1;
break;
}
tindexes.resize(ie - ib + 1);
for(size_t i = 0; i < ie - ib + 1; i++) tindexes[i] = i + ib;
if(tindexes.size() == 0) return {tindexes, "There are no times between " + b.ToString() + " and " + e.ToString()};
pars.SetParameter("timeb", b.ToString());
pars.SetParameter("timee", e.ToString());
}
return {tindexes, ""};
}
template<class D> ReadType<D> Read(const D& data, const MString& vname, const BaseParameters* p, const TIndex& tindex)
{
using RT = ReadType<D>;
size_t ind;
if(tindex.size() == 1)
{
ind = tindex[0];
michlib::message("Time: " + data.Time(ind).ToTString());
if constexpr(ReadPSupported<D>)
return data.Read(vname, p, ind);
else if constexpr(ReadSupported<D>)
return data.Read(vname, ind);
}
else
{
Averager<RT> out;
bool ok = true;
for(size_t i = 0; i < tindex.size(); i++)
{
if(!ok) break;
ind = tindex[i];
michlib::message("Time: " + data.Time(ind).ToTString());
RT dat;
if constexpr(ReadPSupported<D>)
dat = data.Read(vname, p, ind);
else if constexpr(ReadSupported<D>)
dat = data.Read(vname, ind);
if(dat)
out.Add(dat);
else
ok = false;
}
if(ok) return out.Div();
}
return RT();
}
template<class D> UVData<ReadType<D>> ReadUV(const D& data, const BaseParameters* p, size_t ind)
{
using RT = ReadType<D>;
using UV = UVData<RT>;
michlib::message("Time: " + data.Time(ind).ToTString());
RT u, v;
if constexpr(ReadPSupported<D>)
{
u = data.Read("u", p, ind);
v = data.Read("v", p, ind);
}
else if constexpr(ReadSupported<D>)
{
u = data.Read("u", ind);
v = data.Read("v", ind);
}
return UV(u, v);
}
template<class D> UVData<ReadType<D>> ReadUV(const D& data, const BaseParameters* p, const TIndex& tindex)
{
using RT = ReadType<D>;
using UV = UVData<RT>;
if(tindex.size() == 1)
return ReadUV(data, p, tindex[0]);
else
{
Averager<UV> out;
bool ok = true;
size_t ind;
for(size_t i = 0; i < tindex.size(); i++)
{
if(!ok) break;
ind = tindex[i];
michlib::message("Time: " + data.Time(ind).ToTString());
RT u, v;
if constexpr(ReadPSupported<D>)
{
u = data.Read("u", p, ind);
v = data.Read("v", p, ind);
}
else if constexpr(ReadSupported<D>)
{
u = data.Read("u", ind);
v = data.Read("v", ind);
}
UV dat(u, v);
if(dat)
out.Add(dat);
else
ok = false;
}
if(ok) return out.Div();
}
return UV();
}

5
include/basedata.h

@ -10,6 +10,11 @@ class BaseParameters
virtual ~BaseParameters();
};
struct Region
{
real lonb, lone, latb, late;
};
class BaseData
{
protected:

2
include/layereddata.h

@ -133,7 +133,7 @@ class LayeredData: public NCFuncs
public:
MString Info() const;
std::pair<const BaseParameters*, MString> Parameters(michlib_internal::ParameterListEx& pars, const CLArgs& args) const;
std::pair<const BaseParameters*, MString> Parameters(michlib_internal::ParameterListEx& pars, const CLArgs& args, const struct Region& reg) const;
Data Read(const MString& vname, const BaseParameters* ip, size_t i) const;

12
include/traits.h

@ -13,12 +13,22 @@ concept InfoSupported = requires(T t) {
};
template<class T>
concept ParametersSupported = requires(T t, michlib_internal::ParameterListEx& pars, const CLArgs& args) {
concept ParametersRequiredRegion = requires(T t, michlib_internal::ParameterListEx& pars, const CLArgs& args, const struct Region& r) {
{
t.Parameters(pars, args, r).first
} -> std::convertible_to<const BaseParameters*>;
};
template<class T>
concept ParametersNotRequiredRegion = requires(T t, michlib_internal::ParameterListEx& pars, const CLArgs& args) {
{
t.Parameters(pars, args).first
} -> std::convertible_to<const BaseParameters*>;
};
template<class T>
concept ParametersSupported = ParametersRequiredRegion<T> || ParametersNotRequiredRegion<T>;
template<class T>
concept ReadPSupported = requires(T t, const MString& vname, const BaseParameters* ip, size_t i) {
{

11
sources/AVISOLOCAL.cpp

@ -70,14 +70,13 @@ MString AVISOLOCALData::Open(const CLArgs& args)
return "";
}
std::pair<const BaseParameters*, MString> AVISOLOCALData::Parameters(michlib_internal::ParameterListEx& pars, const CLArgs& args) const
std::pair<const BaseParameters*, MString> AVISOLOCALData::Parameters(michlib_internal::ParameterListEx& pars, const CLArgs& args, const struct Region& reg) const
{
std::unique_ptr<struct Parameters> ppar{new struct Parameters};
if(!(args.contains("lonb") && args.contains("lone") && args.contains("latb") && args.contains("late"))) return {nullptr, "Region not specified (lonb, lone, latb, late)"};
ppar->lonb = args.at("lonb").ToReal();
ppar->lone = args.at("lone").ToReal();
ppar->latb = args.at("latb").ToReal();
ppar->late = args.at("late").ToReal();
ppar->lonb = reg.lonb;
ppar->lone = reg.lone;
ppar->latb = reg.latb;
ppar->late = reg.late;
pars.SetParameter("lonb", ppar->lonb);
pars.SetParameter("latb", ppar->latb);

2
sources/AVISOLOCAL.h

@ -37,7 +37,7 @@ class AVISOLOCALData: public NCFuncs
// TODO: RetVal
MString Open(const CLArgs& args);
std::pair<const BaseParameters*, MString> Parameters(michlib_internal::ParameterListEx& pars, const CLArgs& args) const;
std::pair<const BaseParameters*, MString> Parameters(michlib_internal::ParameterListEx& pars, const CLArgs& args, const struct Region& reg) const;
bool isOk() const { return times.size() > 0; }

12
sources/MODISBINLOCAL.cpp

@ -66,14 +66,14 @@ MString MODISBINLOCALData::Open(const CLArgs& args)
return "";
}
std::pair<const BaseParameters*, MString> MODISBINLOCALData::Parameters(michlib_internal::ParameterListEx& pars, const CLArgs& args) const
std::pair<const BaseParameters*, MString> MODISBINLOCALData::Parameters(michlib_internal::ParameterListEx& pars, const CLArgs& args, const struct Region& reg) const
{
std::unique_ptr<struct Parameters> ppar{new struct Parameters};
if(!(args.contains("lonb") && args.contains("lone") && args.contains("latb") && args.contains("late"))) return {nullptr, "Region not specified (lonb, lone, latb, late)"};
ppar->lonb = args.at("lonb").ToReal();
ppar->lone = args.at("lone").ToReal();
ppar->latb = args.at("latb").ToReal();
ppar->late = args.at("late").ToReal();
ppar->lonb = reg.lonb;
ppar->lone = reg.lone;
ppar->latb = reg.latb;
ppar->late = reg.late;
pars.SetParameter("lonb", ppar->lonb);
pars.SetParameter("latb", ppar->latb);

2
sources/MODISBINLOCAL.h

@ -43,7 +43,7 @@ class MODISBINLOCALData
Data Read(const MString& var, const BaseParameters* ip, size_t tind) const;
Data ReadFile(const MString& suf, const struct Parameters* p, size_t tind) const;
std::pair<const BaseParameters*, MString> Parameters(michlib_internal::ParameterListEx& pars, const CLArgs& args) const;
std::pair<const BaseParameters*, MString> Parameters(michlib_internal::ParameterListEx& pars, const CLArgs& args, const struct Region& reg) const;
bool CheckVar(const MString& vname) const
{

12
src/layereddata.cpp

@ -125,7 +125,7 @@ MString LayeredData::Open(const MString& dataset)
return "";
}
std::pair<const BaseParameters*, MString> LayeredData::Parameters(michlib_internal::ParameterListEx& pars, const CLArgs& args) const
std::pair<const BaseParameters*, MString> LayeredData::Parameters(michlib_internal::ParameterListEx& pars, const CLArgs& args, const struct Region& reg) const
{
std::unique_ptr<struct Parameters> ppar{new struct Parameters};
@ -133,14 +133,12 @@ std::pair<const BaseParameters*, MString> LayeredData::Parameters(michlib_intern
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);
if(!(args.contains("lonb") && args.contains("lone") && args.contains("latb") && args.contains("late"))) return {nullptr, "Region not specified (lonb, lone, latb, late)"};
{
auto dom = DetGeoDomain(lonb, lone);
real lon1 = ToGeoDomain(args.at("lonb").ToReal(), dom);
real lon2 = ToGeoDomain(args.at("lone").ToReal(), dom);
real lat1 = args.at("latb").ToReal();
real lat2 = args.at("late").ToReal();
real lon1 = ToGeoDomain(reg.lonb, dom);
real lon2 = ToGeoDomain(reg.lone, dom);
real lat1 = reg.latb;
real lat2 = reg.late;
// Special case when the longitude lies in a small sector between the end and the start
if(lon1 < lonb) lon1 = lone;

Loading…
Cancel
Save