2 changed files with 134 additions and 1 deletions
@ -0,0 +1,117 @@ |
|||||||
|
#define MICHLIB_NOSOURCE |
||||||
|
#include "HYCOM.h" |
||||||
|
#include "CF.h" |
||||||
|
#include <numeric> |
||||||
|
#include <valarray> |
||||||
|
|
||||||
|
using michlib::GPL; |
||||||
|
|
||||||
|
RetVal<Adapter> HYCOMData::GetAdapter(const CLArgs& args, michlib_internal::ParameterListEx& pars) const |
||||||
|
{ |
||||||
|
static const MString pref = "HYCOMData::GetAdapter"; |
||||||
|
|
||||||
|
//const bool debug = args.contains("debug");
|
||||||
|
|
||||||
|
Adapter out(Adapter::ZarrMethod::MNC); |
||||||
|
|
||||||
|
GPL.UsePrefix("HYCOM"); |
||||||
|
|
||||||
|
// Get link for dataset
|
||||||
|
const MString dataset = args.contains("dataset") ? args.at("dataset") : "Forecast"; |
||||||
|
|
||||||
|
pars.AddParameter("dataset", dataset); |
||||||
|
|
||||||
|
std::vector<MString> urls; |
||||||
|
size_t cachettl = GPL.ParameterUValue(dataset + "_CacheTTL", 3600 * 24 * 7); |
||||||
|
{ |
||||||
|
const auto url = GPL.ParameterSValue(dataset + "_URL", ""); |
||||||
|
if(url.Exist()) |
||||||
|
urls.push_back(url); |
||||||
|
else |
||||||
|
{ |
||||||
|
size_t i = 1; |
||||||
|
while(true) |
||||||
|
{ |
||||||
|
const auto url = GPL.ParameterSValue(dataset + "_URL" + i, ""); |
||||||
|
if(!url.Exist()) break; |
||||||
|
urls.push_back(url); |
||||||
|
i++; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if(urls.size() == 0) return {pref, "No urls find for datest " + dataset}; |
||||||
|
|
||||||
|
out.SetTitle(GPL.ParameterSValue(dataset + "_Title", "Unknown")); |
||||||
|
pars.AddParameter("title", out.Title()); |
||||||
|
|
||||||
|
// Open data
|
||||||
|
std::unique_ptr<NCZarr> pnc; |
||||||
|
std::vector<MDateTime> times; |
||||||
|
{ |
||||||
|
std::vector<Adapter::TimeRow> table; |
||||||
|
for(const auto& url: urls) |
||||||
|
{ |
||||||
|
Adapter::TimeRow row; |
||||||
|
std::vector<MDateTime> ltimes; |
||||||
|
|
||||||
|
row.beg = table.size() == 0 ? 0 : (table.back().end + 1); |
||||||
|
row.file = url; |
||||||
|
auto [val, res] = cache->Get(url); |
||||||
|
if(!res) |
||||||
|
{ |
||||||
|
pnc.reset(new NCZarr); |
||||||
|
auto ret = pnc->OpenMultiNC(url.Split(";")); |
||||||
|
if(!ret) return ret.Add(pref, "Can't open link " + url); |
||||||
|
auto tvar = CF::GetTVarName(*pnc); |
||||||
|
if(!tvar.Exist()) return {pref, "Can't find time variable in the dataset " + dataset}; |
||||||
|
if(pnc->NDim(tvar) != 1) return {pref, "Unsupported number of time dimensions: " + MString(pnc->NDim(tvar))}; |
||||||
|
|
||||||
|
auto timesret = CF::ReadTimes(*pnc, tvar); |
||||||
|
if(!timesret) return ret.Add(pref, "Can't read time values from the dataset " + dataset); |
||||||
|
ltimes = timesret.Value(); |
||||||
|
if(ltimes.size() == 0) return {pref, "No time moments in " + url}; |
||||||
|
|
||||||
|
michlib::Serializer s; |
||||||
|
s.Serialize(ltimes.size()); |
||||||
|
for(size_t i = 0; i < ltimes.size(); i++) s.Serialize(ltimes[i]); |
||||||
|
val = MString(s.Buf(), s.Len()); |
||||||
|
cache->Put(url, val, cachettl); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
michlib::Deserializer ds(val.Buf(), val.Len()); |
||||||
|
size_t vsize; |
||||||
|
bool ok; |
||||||
|
ok = ds.Deserialize(vsize); |
||||||
|
if(!ok) return {pref, "Cache line for url " + url + " is bad"}; |
||||||
|
ltimes.resize(vsize); |
||||||
|
for(size_t i = 0; i < vsize; i++) ok = ok && ds.Deserialize(ltimes[i]); |
||||||
|
if(!ok) return {pref, "Cache line for url " + url + " is bad"}; |
||||||
|
} |
||||||
|
row.end = row.beg + ltimes.size() - 1; |
||||||
|
times.insert(times.end(), ltimes.begin(), ltimes.end()); |
||||||
|
table.push_back(row); |
||||||
|
} |
||||||
|
out.SetTimeTable(std::move(table)); |
||||||
|
} |
||||||
|
|
||||||
|
if(!pnc) |
||||||
|
{ |
||||||
|
pnc.reset(new NCZarr); |
||||||
|
auto ret = pnc->OpenMultiNC(urls[0].Split(";")); |
||||||
|
if(!ret) return ret.Add(pref, "Can't open link " + urls[0]); |
||||||
|
} |
||||||
|
|
||||||
|
// Set times
|
||||||
|
{ |
||||||
|
auto ret = out.SetTimes(std::move(times), args, pars); |
||||||
|
if(!ret) return ret.Add(pref, "Can't filter time values from the dataset " + dataset); |
||||||
|
} |
||||||
|
|
||||||
|
{ |
||||||
|
auto ret = CF::FillAdapterFromCF(args, pars, out, std::move(pnc)); |
||||||
|
if(!ret) return ret.Add(pref, "Can't get adapter"); |
||||||
|
} |
||||||
|
|
||||||
|
return out; |
||||||
|
} |
Loading…
Reference in new issue