|
|
|
@ -1,8 +1,11 @@
|
|
|
|
|
#define MICHLIB_NOSOURCE |
|
|
|
|
#include "COPERNICUS.h" |
|
|
|
|
#include "CF.h" |
|
|
|
|
#include "mirrorfuncs.h" |
|
|
|
|
#include <libxml/parser.h> |
|
|
|
|
#include <libxml/tree.h> |
|
|
|
|
#include <numeric> |
|
|
|
|
#include <valarray> |
|
|
|
|
|
|
|
|
|
using michlib::GPL; |
|
|
|
|
|
|
|
|
@ -232,3 +235,113 @@ Error COPERNICUSData::Mirror(const CLArgs& args) const
|
|
|
|
|
|
|
|
|
|
return Error(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
RetVal<Adapter> COPERNICUSData::GetAdapter(const CLArgs& args, michlib_internal::ParameterListEx& pars) const |
|
|
|
|
{ |
|
|
|
|
static const MString pref = "COPERNICUSData::GetAdapter"; |
|
|
|
|
|
|
|
|
|
bool debug = args.contains("debug"); |
|
|
|
|
|
|
|
|
|
Adapter out(Adapter::ZarrMethod::MZARR); |
|
|
|
|
|
|
|
|
|
MString dataset = args.contains("dataset") ? args.at("dataset") : "DT"; |
|
|
|
|
|
|
|
|
|
GPL.UsePrefix("NEMO"); |
|
|
|
|
|
|
|
|
|
// Get link for dataset
|
|
|
|
|
MString product; |
|
|
|
|
std::vector<MString> dset; |
|
|
|
|
{ |
|
|
|
|
// Try one url
|
|
|
|
|
MString url = GPL.ParameterSValue(dataset + "_URL", ""); |
|
|
|
|
if(url.Exist()) |
|
|
|
|
{ |
|
|
|
|
auto list = url.Split(":"); |
|
|
|
|
product = list[0]; |
|
|
|
|
for(size_t i = 1; i < list.size(); i++) dset.push_back(list[i]); |
|
|
|
|
} |
|
|
|
|
else // Multiple urls
|
|
|
|
|
{ |
|
|
|
|
size_t i = 1; |
|
|
|
|
while(true) |
|
|
|
|
{ |
|
|
|
|
MString url = GPL.ParameterSValue(dataset + "_URL" + i, ""); |
|
|
|
|
if(url.Exist()) |
|
|
|
|
{ |
|
|
|
|
// Split url on product and dataset
|
|
|
|
|
auto words = url.Split(":"); |
|
|
|
|
if(words.size() != 2) return {pref, "Invalid url for dataset " + dataset + ": " + url}; |
|
|
|
|
if(product.Exist() && product != words[0]) return {pref, "Product for dataset " + dataset + " was already defined: " + url}; |
|
|
|
|
product = words[0]; |
|
|
|
|
dset.push_back(words[1]); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
break; |
|
|
|
|
i++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if(!product.Exist()) return {pref, "Can't find product for the dataset " + dataset}; |
|
|
|
|
if(dset.size() == 0) // Get datasets from catalog
|
|
|
|
|
{ |
|
|
|
|
CopernicusCatalog cat; |
|
|
|
|
auto dlist = cat.DatasetList(product); |
|
|
|
|
if(!dlist) return dlist.Add(pref, "Can't get list of datasets for product " + product); |
|
|
|
|
dset = dlist.Value(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pars.AddParameter("product", product); |
|
|
|
|
pars.AddParameter("datasets", std::accumulate(dset.begin() + 1, dset.end(), dset.front(), [](const MString& a, const MString& b) { return a + "," + b; })); |
|
|
|
|
|
|
|
|
|
// Open data
|
|
|
|
|
std::unique_ptr<NCZarr> pnc(new NCZarr); |
|
|
|
|
{ |
|
|
|
|
auto ret = pnc->OpenMultiZarr(product, dset); |
|
|
|
|
if(!ret) return ret.Add(pref, "Can't open dataset " + dataset); |
|
|
|
|
} |
|
|
|
|
pars.AddParameter("dataset", dataset); |
|
|
|
|
|
|
|
|
|
// Title
|
|
|
|
|
{ |
|
|
|
|
MString title; |
|
|
|
|
CopernicusCatalog cat; |
|
|
|
|
auto ret = cat.DatasetTitle(product, dset[0]); |
|
|
|
|
if(!ret) return ret.Add(pref, "Can't get title for dataset " + dataset); |
|
|
|
|
title = ret.Value(); |
|
|
|
|
pars.AddParameter("title", title); |
|
|
|
|
out.SetTitle(title); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Filename for adapter
|
|
|
|
|
MString fname = product + ":" + dset[0]; |
|
|
|
|
for(size_t i = 1; i < dset.size(); i++) fname += "," + dset[i]; |
|
|
|
|
|
|
|
|
|
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))}; |
|
|
|
|
if(debug) pars.AddParameter("File name", fname); |
|
|
|
|
|
|
|
|
|
// Read and set times
|
|
|
|
|
{ |
|
|
|
|
auto ret = CF::ReadTimes(*pnc, tvar); |
|
|
|
|
if(!ret) return ret.Add(pref, "Can't read time values from the dataset " + dataset); |
|
|
|
|
auto ret1 = out.SetTimes(ret.Value(), args, pars); |
|
|
|
|
if(!ret1) return ret1.Add(pref, "Can't filter time values from the dataset " + dataset); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Timetable
|
|
|
|
|
{ |
|
|
|
|
std::vector<Adapter::TimeRow> table{1}; |
|
|
|
|
table[0].beg = 0; |
|
|
|
|
table[0].end = out.Times().size() - 1; |
|
|
|
|
table[0].file = fname; |
|
|
|
|
out.SetTimeTable(std::move(table)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
auto ret = CF::FillAdapterFromCF(args, pars, out, std::move(pnc)); |
|
|
|
|
if(!ret) return ret.Add(pref, "Can't get adapter"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return out; |
|
|
|
|
} |
|
|
|
|