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 |
||||
#include "AVISO.h" |
||||
#include "AVISOLOCAL.h" |
||||
#include "BFileW.h" |
||||
#include "HYCOM.h" |
||||
#include "NEMO.h" |
||||
#include <utility> |
||||
#include <variant> |
||||
#include "actioninfo.h" |
||||
#include "actiontsc.h" |
||||
#include "actionuv.h" |
||||
#include "data.h" |
||||
|
||||
using michlib::BFileW; |
||||
using michlib::errmessage; |
||||
using michlib::GPL; |
||||
using michlib::message; |
||||
|
||||
using DataVariants = std::variant<NEMOData, HYCOMData, AVISOData, AVISOLOCALData>; |
||||
|
||||
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) |
||||
} -> std::convertible_to<real>; |
||||
}; |
||||
|
||||
class Data: public DataVariants |
||||
template<class T, ActionID id> consteval bool MustSupported() |
||||
{ |
||||
public: |
||||
using TIndex = std::vector<size_t>; |
||||
|
||||
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); |
||||
static_assert(IsActionSupported<T, id>); |
||||
return true; |
||||
}; |
||||
|
||||
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>() && |
||||
MustSupported<AVISOData, ActionID::INFO>() && MustSupported<AVISOData, ActionID::TSC>() && MustSupported<AVISOData, ActionID::UV>() && |
||||
MustSupported<AVISOLOCALData, ActionID::INFO>() && MustSupported<AVISOLOCALData, ActionID::TSC>() && MustSupported<AVISOLOCALData, ActionID::UV>(); |
||||
|
@ -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" |
||||
|
||||
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