Michael Uleysky
2 years ago
22 changed files with 737 additions and 567 deletions
@ -0,0 +1,17 @@ |
|||||||
|
#pragma once |
||||||
|
#include "actions.h" |
||||||
|
|
||||||
|
using michlib::message; |
||||||
|
|
||||||
|
template<class D> struct DoAction_<D, ActionID::INFO> |
||||||
|
{ |
||||||
|
static MString DoAction(const CLArgs& args, D& data); |
||||||
|
}; |
||||||
|
|
||||||
|
template<class D> MString DoAction_<D, ActionID::INFO>::DoAction([[maybe_unused]] const CLArgs& args, D& data) |
||||||
|
{ |
||||||
|
auto info = data.Info(); |
||||||
|
if(!info.Exist()) return "No info"; |
||||||
|
message(info); |
||||||
|
return ""; |
||||||
|
}; |
@ -0,0 +1,246 @@ |
|||||||
|
#pragma once |
||||||
|
#include "basedata.h" |
||||||
|
#include "mdatetime.h" |
||||||
|
#include "mregex.h" |
||||||
|
#include "uvdata.h" |
||||||
|
#include <variant> |
||||||
|
|
||||||
|
using michlib::BFileW; |
||||||
|
using michlib::MDateTime; |
||||||
|
|
||||||
|
using TIndex = std::vector<size_t>; |
||||||
|
|
||||||
|
enum class ActionID |
||||||
|
{ |
||||||
|
INFO, |
||||||
|
TSC, |
||||||
|
UV |
||||||
|
}; |
||||||
|
|
||||||
|
template<ActionID id> struct ActionCarrier |
||||||
|
{ |
||||||
|
constexpr static ActionID action = id; |
||||||
|
}; |
||||||
|
|
||||||
|
template<class T, ActionID id> struct IsActionSupportedTest |
||||||
|
{ |
||||||
|
static constexpr bool ans = false; |
||||||
|
}; |
||||||
|
|
||||||
|
template<class T> struct IsActionSupportedTest<T, ActionID::INFO> |
||||||
|
{ |
||||||
|
static constexpr bool ans = InfoSupported<T>; |
||||||
|
}; |
||||||
|
template<class T> struct IsActionSupportedTest<T, ActionID::TSC> |
||||||
|
{ |
||||||
|
static constexpr bool ans = ReadPSupported<T> || ReadSupported<T>; |
||||||
|
}; |
||||||
|
template<class T> struct IsActionSupportedTest<T, ActionID::UV> |
||||||
|
{ |
||||||
|
static constexpr bool ans = ReadPSupported<T> || ReadSupported<T>; |
||||||
|
}; |
||||||
|
|
||||||
|
template<class T, ActionID id> constexpr bool IsActionSupported = IsActionSupportedTest<T, id>::ans; |
||||||
|
|
||||||
|
using ActionVariants = std::variant<ActionCarrier<ActionID::INFO>, ActionCarrier<ActionID::TSC>, ActionCarrier<ActionID::UV>>; |
||||||
|
|
||||||
|
class Action: public ActionVariants |
||||||
|
{ |
||||||
|
public: |
||||||
|
Action() = default; |
||||||
|
Action(ActionVariants&& d): ActionVariants(std::move(d)) {} |
||||||
|
MString Init(const CLArgs& args) |
||||||
|
{ |
||||||
|
MString act = args.contains("action") ? args.at("action") : "info"; |
||||||
|
if(act == "info") |
||||||
|
*this = ActionVariants(ActionCarrier<ActionID::INFO>()); |
||||||
|
else if(act == "tsc") |
||||||
|
*this = ActionVariants(ActionCarrier<ActionID::TSC>()); |
||||||
|
else if(act == "uv") |
||||||
|
*this = ActionVariants(ActionCarrier<ActionID::UV>()); |
||||||
|
else |
||||||
|
return "Unknown action: " + act; |
||||||
|
return ""; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
template<class D, ActionID id> struct DoAction_ |
||||||
|
{ |
||||||
|
static MString DoAction(const CLArgs& args, D& data) { return "Internal error"; } |
||||||
|
}; |
||||||
|
|
||||||
|
template<ActionID id, class D> MString DoAction(const CLArgs& args, D& data) { return DoAction_<D, id>::DoAction(args, data); } |
||||||
|
|
||||||
|
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> BaseData 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 BaseData(); |
||||||
|
} |
||||||
|
|
||||||
|
template<class D> UVData<ReadType<D>> ReadUV(const D& data, const BaseParameters* p, const TIndex& tindex) |
||||||
|
{ |
||||||
|
using RT = ReadType<D>; |
||||||
|
using UV = UVData<RT>; |
||||||
|
size_t ind; |
||||||
|
if(tindex.size() == 1) |
||||||
|
{ |
||||||
|
ind = tindex[0]; |
||||||
|
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); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
Averager<UV> 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 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(); |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
#pragma once |
||||||
|
#include "actions.h" |
||||||
|
|
||||||
|
template<class D> struct DoAction_<D, ActionID::TSC> |
||||||
|
{ |
||||||
|
static MString DoAction(const CLArgs& args, D& data); |
||||||
|
}; |
||||||
|
|
||||||
|
template<class D> MString DoAction_<D, ActionID::TSC>::DoAction(const CLArgs& args, D& ds) |
||||||
|
{ |
||||||
|
michlib_internal::ParameterListEx pars; |
||||||
|
pars.UsePrefix(""); |
||||||
|
pars.SetParameter("source", args.at("source")); |
||||||
|
|
||||||
|
auto [tindexes, err] = GetTIndexes(ds, args, pars); |
||||||
|
if(err.Exist()) return err; |
||||||
|
|
||||||
|
if(!args.contains("var")) return "Variable not specified"; |
||||||
|
MString vname = args.at("var"); |
||||||
|
if(!ds.CheckVar(vname)) return "Variable " + vname + " not exists in this dataset"; |
||||||
|
pars.SetParameter("variable", vname); |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
auto p = sourcepars.get(); |
||||||
|
|
||||||
|
auto data = Read(ds, vname, p, tindexes); |
||||||
|
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); |
||||||
|
fw.SetColumnName(1, "Longitude"); |
||||||
|
fw.SetColumnName(2, "Latitude"); |
||||||
|
fw.SetColumnName(3, vname); |
||||||
|
fw.SetParameters(pars); |
||||||
|
for(size_t i = 0; i < data.N(); i++) |
||||||
|
{ |
||||||
|
fw.Write(data.Lon(i)); |
||||||
|
fw.Write(data.Lat(i)); |
||||||
|
fw.Write(data(i) == data.Fillval() ? NAN : data(i)); |
||||||
|
} |
||||||
|
fw.Finalize(); |
||||||
|
fw.Close(); |
||||||
|
|
||||||
|
return ""; |
||||||
|
}; |
@ -0,0 +1,16 @@ |
|||||||
|
#pragma once |
||||||
|
#include "AVISO.h" |
||||||
|
#include "AVISOLOCAL.h" |
||||||
|
#include "HYCOM.h" |
||||||
|
#include "NEMO.h" |
||||||
|
#include <variant> |
||||||
|
|
||||||
|
using DataVariants = std::variant<NEMOData, HYCOMData, AVISOData, AVISOLOCALData>; |
||||||
|
class Data: public DataVariants |
||||||
|
{ |
||||||
|
public: |
||||||
|
Data() = default; |
||||||
|
Data(DataVariants&& v): DataVariants(std::move(v)) {} |
||||||
|
|
||||||
|
MString Init(const CLArgs& args); |
||||||
|
}; |
@ -1,180 +1,18 @@ |
|||||||
#pragma once |
#pragma once |
||||||
#include "AVISO.h" |
#include "actioninfo.h" |
||||||
#include "AVISOLOCAL.h" |
#include "actiontsc.h" |
||||||
#include "BFileW.h" |
#include "actionuv.h" |
||||||
#include "HYCOM.h" |
#include "data.h" |
||||||
#include "NEMO.h" |
|
||||||
#include <utility> |
|
||||||
#include <variant> |
|
||||||
|
|
||||||
using michlib::BFileW; |
|
||||||
using michlib::errmessage; |
using michlib::errmessage; |
||||||
using michlib::GPL; |
|
||||||
using michlib::message; |
|
||||||
|
|
||||||
using DataVariants = std::variant<NEMOData, HYCOMData, AVISOData, AVISOLOCALData>; |
template<class T, ActionID id> consteval bool MustSupported() |
||||||
|
|
||||||
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 MString& vname, const BaseParameters* ip, size_t i) { |
|
||||||
{ |
|
||||||
t.template Read(vname, ip, i)(0) |
|
||||||
} -> std::convertible_to<real>; |
|
||||||
}; |
|
||||||
template<class T> |
|
||||||
concept ReadSupported = requires(T t, const MString& vname, size_t i) { |
|
||||||
{ |
|
||||||
t.template Read(vname, i)(0) |
|
||||||
} -> std::convertible_to<real>; |
|
||||||
}; |
|
||||||
|
|
||||||
template<class T> |
|
||||||
concept ReadUVPSupported = requires(T t, const BaseParameters* ip, size_t i) { |
|
||||||
{ |
{ |
||||||
t.template ReadUV(ip, i).U(0, 0) + t.template ReadUV(ip, i).V(0, 0) |
static_assert(IsActionSupported<T, id>); |
||||||
} -> std::convertible_to<real>; |
return true; |
||||||
}; |
}; |
||||||
|
|
||||||
class Data: public DataVariants |
constexpr bool supported = MustSupported<NEMOData, ActionID::INFO>() && MustSupported<NEMOData, ActionID::TSC>() && MustSupported<NEMOData, ActionID::UV>() && |
||||||
{ |
MustSupported<HYCOMData, ActionID::INFO>() && MustSupported<HYCOMData, ActionID::TSC>() && MustSupported<HYCOMData, ActionID::UV>() && |
||||||
public: |
MustSupported<AVISOData, ActionID::INFO>() && MustSupported<AVISOData, ActionID::TSC>() && MustSupported<AVISOData, ActionID::UV>() && |
||||||
using TIndex = std::vector<size_t>; |
MustSupported<AVISOLOCALData, ActionID::INFO>() && MustSupported<AVISOLOCALData, ActionID::TSC>() && MustSupported<AVISOLOCALData, ActionID::UV>(); |
||||||
|
|
||||||
private: |
|
||||||
TIndex GetTIndexes(const MDateTime& b, const MDateTime& e) const |
|
||||||
{ |
|
||||||
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++) |
|
||||||
{ |
|
||||||
MString date = Time(i).ToString(); |
|
||||||
if(0 != regexec(regbuf.get(), date.Buf(), 0, 0, 0)) continue; |
|
||||||
out.push_back(i); |
|
||||||
} |
|
||||||
|
|
||||||
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: |
|
||||||
Data() = default; |
|
||||||
|
|
||||||
Data(DataVariants&& d): DataVariants(std::move(d)) {} |
|
||||||
|
|
||||||
MDateTime Time(size_t it) const |
|
||||||
{ |
|
||||||
return std::visit([it = it](const auto& arg) -> auto { return arg.Time(it); }, *this); |
|
||||||
} |
|
||||||
size_t NTimes() const |
|
||||||
{ |
|
||||||
return std::visit([](const auto& arg) -> auto { return arg.NTimes(); }, *this); |
|
||||||
} |
|
||||||
|
|
||||||
auto CheckVar(const MString& vname) const |
|
||||||
{ |
|
||||||
return std::visit([&vname = std::as_const(vname)](const auto& arg) -> auto { return arg.CheckVar(vname); }, *this); |
|
||||||
} |
|
||||||
|
|
||||||
MString Init(const CLArgs& args) |
|
||||||
{ |
|
||||||
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 if(src == "AVISO") |
|
||||||
{ |
|
||||||
AVISOData data; |
|
||||||
auto res = data.Open(args); |
|
||||||
if(res.Exist()) return "Can't open source " + src + ":\n" + res; |
|
||||||
*this = Data(std::move(data)); |
|
||||||
} |
|
||||||
else if(src == "AVISOLOCAL") |
|
||||||
{ |
|
||||||
AVISOLOCALData data; |
|
||||||
auto res = data.Open(args); |
|
||||||
if(res.Exist()) return "Can't open source " + src + ":\n" + res; |
|
||||||
*this = Data(std::move(data)); |
|
||||||
} |
|
||||||
else if(src == "HYCOM") |
|
||||||
{ |
|
||||||
HYCOMData 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 ""; |
|
||||||
} |
|
||||||
|
|
||||||
MString ActionInfo(const CLArgs& args); |
|
||||||
MString ActionTsc(const CLArgs& args); |
|
||||||
MString ActionUV(const CLArgs& args); |
|
||||||
}; |
|
||||||
|
@ -0,0 +1,74 @@ |
|||||||
|
#pragma once |
||||||
|
#include "ParseArgs.h" |
||||||
|
#include <concepts> |
||||||
|
|
||||||
|
class BaseParameters; |
||||||
|
using michlib::real; |
||||||
|
|
||||||
|
template<class T> |
||||||
|
concept InfoSupported = requires(T t) { |
||||||
|
{ |
||||||
|
t.Info() |
||||||
|
} -> std::convertible_to<MString>; |
||||||
|
}; |
||||||
|
|
||||||
|
template<class T> |
||||||
|
concept ParametersSupported = requires(T t, michlib_internal::ParameterListEx& pars, const CLArgs& args) { |
||||||
|
{ |
||||||
|
t.Parameters(pars, args).first |
||||||
|
} -> std::convertible_to<const BaseParameters*>; |
||||||
|
}; |
||||||
|
|
||||||
|
template<class T> |
||||||
|
concept ReadPSupported = requires(T t, const MString& vname, const BaseParameters* ip, size_t i) { |
||||||
|
{ |
||||||
|
t.Read(vname, ip, i)(0) |
||||||
|
} -> std::convertible_to<real>; |
||||||
|
}; |
||||||
|
template<class T> |
||||||
|
concept ReadSupported = requires(T t, const MString& vname, size_t i) { |
||||||
|
{ |
||||||
|
t.Read(vname, i)(0) |
||||||
|
} -> std::convertible_to<real>; |
||||||
|
}; |
||||||
|
|
||||||
|
template<class T> |
||||||
|
concept ReadUVPSupported = requires(T t, const BaseParameters* ip, size_t i) { |
||||||
|
{ |
||||||
|
t.ReadUV(ip, i).U(0, 0) + t.template ReadUV(ip, i).V(0, 0) |
||||||
|
} -> std::convertible_to<real>; |
||||||
|
}; |
||||||
|
|
||||||
|
template<class T> |
||||||
|
concept IsUVData = requires(T t) { |
||||||
|
{ |
||||||
|
t.U(0) |
||||||
|
} -> std::convertible_to<real>; |
||||||
|
{ |
||||||
|
t.V(0) |
||||||
|
} -> std::convertible_to<real>; |
||||||
|
{ |
||||||
|
t.U2(0) |
||||||
|
} -> std::convertible_to<real>; |
||||||
|
}; |
||||||
|
|
||||||
|
namespace internal |
||||||
|
{ |
||||||
|
template<typename...> using void_ = void; |
||||||
|
|
||||||
|
template<class D, bool RP, bool R> struct GetReadType_; |
||||||
|
|
||||||
|
template<class D, bool R> struct GetReadType_<D, true, R> |
||||||
|
{ |
||||||
|
using p = BaseParameters*; |
||||||
|
using type = decltype(D().Read(MString(), p(), 0)); |
||||||
|
}; |
||||||
|
|
||||||
|
template<class D> struct GetReadType_<D, false, true> |
||||||
|
{ |
||||||
|
using type = decltype(D().Read(MString(), 0)); |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
template<class D> using ReadType = internal::GetReadType_<D, ReadPSupported<D>, ReadSupported<D>>::type; |
@ -1,19 +0,0 @@ |
|||||||
#define MICHLIB_NOSOURCE |
|
||||||
#include "odm.h" |
|
||||||
|
|
||||||
MString Data::ActionInfo(const CLArgs& args) |
|
||||||
{ |
|
||||||
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 ""; |
|
||||||
} |
|
@ -1,113 +0,0 @@ |
|||||||
#define MICHLIB_NOSOURCE |
|
||||||
#include "GPL.h" |
|
||||||
#include "odm.h" |
|
||||||
|
|
||||||
MString Data::ActionTsc(const CLArgs& args) |
|
||||||
{ |
|
||||||
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")); |
|
||||||
TIndex tindexes; |
|
||||||
|
|
||||||
if(args.contains("time")) |
|
||||||
{ |
|
||||||
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 |
|
||||||
{ |
|
||||||
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("var")) return "Variable not specified"; |
|
||||||
MString vname = args.at("var"); |
|
||||||
if(!CheckVar(vname)) return "Variable " + vname + " not exists in this dataset"; |
|
||||||
pars.SetParameter("variable", vname); |
|
||||||
|
|
||||||
std::unique_ptr<const BaseParameters> sourcepars; |
|
||||||
{ |
|
||||||
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); |
|
||||||
} |
|
||||||
|
|
||||||
auto p = sourcepars.get(); |
|
||||||
size_t ind; |
|
||||||
auto read = [&vname = std::as_const(vname), p = p, &ind = ind](const auto& arg) -> BaseData |
|
||||||
{ |
|
||||||
using T = std::decay_t<decltype(arg)>; |
|
||||||
if constexpr(ParametersSupported<T> && ReadPSupported<T>) |
|
||||||
return arg.Read(vname, p, ind); |
|
||||||
else if constexpr(!ParametersSupported<T> && ReadSupported<T>) |
|
||||||
return arg.Read(vname, ind); |
|
||||||
else |
|
||||||
return BaseData(); |
|
||||||
}; |
|
||||||
|
|
||||||
BaseData data; |
|
||||||
if(tindexes.size() == 1) |
|
||||||
{ |
|
||||||
ind = tindexes[0]; |
|
||||||
michlib::message("Time: " + Time(ind).ToTString()); |
|
||||||
data = std::visit(read, *this); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
Averager<BaseData> out; |
|
||||||
bool ok = true; |
|
||||||
for(size_t i = 0; i < tindexes.size(); i++) |
|
||||||
{ |
|
||||||
if(!ok) break; |
|
||||||
ind = tindexes[i]; |
|
||||||
michlib::message("Time: " + Time(ind).ToTString()); |
|
||||||
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); |
|
||||||
fw.SetColumnName(1, "Longitude"); |
|
||||||
fw.SetColumnName(2, "Latitude"); |
|
||||||
fw.SetColumnName(3, vname); |
|
||||||
fw.SetParameters(pars); |
|
||||||
for(size_t i = 0; i < data.N(); i++) |
|
||||||
{ |
|
||||||
fw.Write(data.Lon(i)); |
|
||||||
fw.Write(data.Lat(i)); |
|
||||||
fw.Write(data(i) == data.Fillval() ? NAN : data(i)); |
|
||||||
} |
|
||||||
fw.Finalize(); |
|
||||||
fw.Close(); |
|
||||||
|
|
||||||
return ""; |
|
||||||
} |
|
@ -1,3 +1,4 @@ |
|||||||
|
#define MICHLIB_NOSOURCE |
||||||
#include "basedata.h" |
#include "basedata.h" |
||||||
|
|
||||||
BaseParameters::~BaseParameters() {} |
BaseParameters::~BaseParameters() {} |
||||||
|
@ -0,0 +1,39 @@ |
|||||||
|
#define MICHLIB_NOSOURCE |
||||||
|
#include "data.h" |
||||||
|
|
||||||
|
MString Data::Init(const CLArgs& args) |
||||||
|
{ |
||||||
|
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 if(src == "AVISO") |
||||||
|
{ |
||||||
|
AVISOData data; |
||||||
|
auto res = data.Open(args); |
||||||
|
if(res.Exist()) return "Can't open source " + src + ":\n" + res; |
||||||
|
*this = Data(std::move(data)); |
||||||
|
} |
||||||
|
else if(src == "AVISOLOCAL") |
||||||
|
{ |
||||||
|
AVISOLOCALData data; |
||||||
|
auto res = data.Open(args); |
||||||
|
if(res.Exist()) return "Can't open source " + src + ":\n" + res; |
||||||
|
*this = Data(std::move(data)); |
||||||
|
} |
||||||
|
else if(src == "HYCOM") |
||||||
|
{ |
||||||
|
HYCOMData 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 ""; |
||||||
|
} |
Loading…
Reference in new issue