Browse Source

Adapter support for HYCOM

master
Michael Uleysky 2 weeks ago
parent
commit
bba5f9c054
  1. 117
      sources/HYCOM.cpp
  2. 18
      sources/HYCOM.h

117
sources/HYCOM.cpp

@ -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;
}

18
sources/HYCOM.h

@ -14,10 +14,23 @@ class HYCOMData: public LayeredData
Type type = TYPE_UNKNOWN;
std::unique_ptr<GenericCache> cache;
public:
static constexpr const char* name = "HYCOM";
HYCOMData() = default;
HYCOMData()
{
auto oldprefix = michlib::GPL.UsePrefix("HYCOM");
// Cache
cache.reset(CreateCache(michlib::GPL.ParameterSValue("Cache", "")));
if(!cache)
{
michlib::errmessage("Can't init cache");
cache.reset(new FakeCache);
}
michlib::GPL.UsePrefix(oldprefix);
}
MString DataTitle() const
{
@ -51,4 +64,7 @@ class HYCOMData: public LayeredData
SetTitle(DataTitle());
return LayeredData::Open(dataset);
}
// Adapter
RetVal<Adapter> GetAdapter(const CLArgs& args, michlib_internal::ParameterListEx& pars) const;
};

Loading…
Cancel
Save