You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
210 lines
6.5 KiB
210 lines
6.5 KiB
#pragma once |
|
#include "CF.h" |
|
#include "actiondep.h" |
|
|
|
using michlib::message; |
|
using michlib::uint2; |
|
|
|
ADD_ACTION(Info, info, (InfoSupported<Source> || AdapterSupported<Source>)); |
|
|
|
template<class D> MString ActionInfo_DoAction(const CLArgs& args, D& data); |
|
|
|
template<class D> MString ActionInfo::DoAction(const CLArgs& args, D& data) { return ActionInfo_DoAction(args, data); } |
|
|
|
template<class D> |
|
requires AdapterSupported<D> |
|
MString ActionInfo_DoAction(const CLArgs& args, D& data) |
|
{ |
|
Adapter ad; |
|
michlib_internal::ParameterListEx pars; |
|
pars.UsePrefix(""); |
|
{ |
|
auto ret = data.GetAdapter(args, pars); |
|
if(!ret) return "Error opening source"; |
|
ad = std::move(ret.Value()); |
|
} |
|
|
|
// Modules |
|
{ |
|
auto ret = CF::TEOS10Module(args, pars, ad); |
|
if(!ret) return "Error adding TEOS-10 derived variables"; |
|
} |
|
{ |
|
auto ret = CF::GeostrophicModule(args, pars, ad); |
|
if(!ret) return "Error adding geostrophic velocity"; |
|
} |
|
|
|
const MString titCol = F(C::BWHITE); |
|
const MString timeCol = F(C::YELLOW); |
|
const MString v2dCol = F(C::BGREEN); |
|
const MString v3dCol = F(C::CYAN); |
|
const MString unitCol = F(C::YELLOW); |
|
const MString usedCol = F(C::BMAGENTA); |
|
const MString depthCol = F(C::YELLOW); |
|
const MString horCol = F(C::YELLOW); |
|
const MString comCol = F(C::BYELLOW); |
|
|
|
// Header |
|
message(titCol, ad.Title(), C()); |
|
// All times |
|
{ |
|
const auto& times = ad.Times(); |
|
|
|
const bool onetime = times.size() == 1; |
|
const bool uniform = CF::CheckUniform(times); |
|
|
|
MString out = MString("Time moments: ") + timeCol + times.size() + C(); |
|
if(onetime) |
|
out += ", " + timeCol + times[0].ToTString() + C(); |
|
else |
|
out += ", from " + timeCol + times.front().ToTString() + C() + " to " + timeCol + times.back().ToTString() + C(); |
|
if(!onetime && !uniform) out += ", not uniform"; |
|
if(uniform) out += ", step is " + timeCol + (times.back() - times.front()).Seconds() / (times.size() - 1) + C() + " s"; |
|
message(out); |
|
} |
|
|
|
// Selected times |
|
{ |
|
const auto times = ad.TimeIndexes() | std::views::transform([× = ad.Times()](size_t i) { return times[i]; }); |
|
|
|
const bool onetime = times.size() == 1; |
|
const bool uniform = CF::CheckUniform(times); |
|
|
|
MString out = MString("Selected time moments: ") + timeCol + times.size() + C(); |
|
if(onetime) |
|
out += ", " + timeCol + times[0].ToTString() + C(); |
|
else |
|
out += ", from " + timeCol + times.front().ToTString() + C() + " to " + timeCol + times.back().ToTString() + C(); |
|
if(!onetime && !uniform) out += ", not uniform"; |
|
if(uniform) out += ", step is " + timeCol + (times.back() - times.front()).Seconds() / (times.size() - 1) + C() + " s"; |
|
message(out); |
|
|
|
// Holes |
|
if(times.size() > 1 && !uniform && args.contains("showholes")) |
|
{ |
|
auto delta = times[1] - times[0]; |
|
for(size_t i = 1; i < times.size(); i++) delta = std::min(delta, times[i] - times[i - 1]); |
|
|
|
out = "Holes:"; |
|
|
|
auto time = times[0]; |
|
size_t i = 0; |
|
while(time + delta <= times.back() || i >= times.size()) |
|
{ |
|
if(time != times[i]) |
|
out += " " + time.ToTString(); |
|
else |
|
i++; |
|
time += delta; |
|
} |
|
message(out); |
|
} |
|
} |
|
|
|
// Variables |
|
std::map<std::shared_ptr<Projection>, MString> usedproj; |
|
std::map<std::shared_ptr<Vertical>, MString> usedvert; |
|
for(const auto& v: ad.Vars()) |
|
{ |
|
const auto& name = v.first; |
|
const auto& info = v.second.info; |
|
const auto& proj = v.second.proj; |
|
const auto& vert = v.second.vert; |
|
|
|
message(""); |
|
|
|
// Metainfo |
|
message(ad.Is2D(name) ? v2dCol : v3dCol, name, C(), info->lname.Exist() ? (" - " + info->lname) : "", |
|
info->targetunit.Exist() ? (", measured in " + unitCol + info->targetunit + C()) : ""); |
|
if(info->comment.Exist()) message(comCol, " ", info->comment, C()); |
|
if(info->stname.Exist()) message(" Standard name: " + info->stname); |
|
|
|
// Vertical grid description |
|
if(!ad.Is2D(name)) |
|
{ |
|
if(usedvert.contains(vert)) |
|
message(" Vertical grid is same as for ", usedCol, usedvert[vert], C()); |
|
else |
|
{ |
|
MString out = " Vertical grid: "; |
|
switch(vert->Type()) |
|
{ |
|
case(Vertical::Type::LAYERS): |
|
{ |
|
out += depthCol + vert->Nz() + C() + " layers"; |
|
break; |
|
} |
|
case(Vertical::Type::HORIZONTS): |
|
{ |
|
out += depthCol + vert->Nz() + C() + " horizonts,"; |
|
for(size_t i = 0; i < vert->Nz(); i++) { out += " (" + MString(i) + " " + depthCol + vert->Depth(i) + C() + " m)"; } |
|
break; |
|
} |
|
case(Vertical::Type::GRID): |
|
{ |
|
out += depthCol + vert->Nz() + C() + " horizonts, from " + depthCol + vert->Depth(0) + C() + "m to " + depthCol + vert->Depth(vert->Nz() - 1) + C() + "m, step " + depthCol + |
|
(vert->Depth(vert->Nz() - 1) - vert->Depth(0)) / (vert->Nz() - 1) + C() + "m"; |
|
break; |
|
} |
|
case(Vertical::Type::FIXED): |
|
{ |
|
out += depthCol + vert->Depth(0) + C() + " m"; |
|
break; |
|
} |
|
case(Vertical::Type::UNDEFINED): |
|
{ |
|
out += "undefined"; |
|
break; |
|
} |
|
} |
|
message(out); |
|
usedvert[vert] = name; |
|
} |
|
} |
|
|
|
// Horizontal grid description |
|
if(usedproj.contains(proj)) |
|
message(" Horizontal grid is same as for ", usedCol, usedproj[proj], C()); |
|
else |
|
{ |
|
MString out = " Horizontal grid: "; |
|
|
|
switch(proj->Type()) |
|
{ |
|
case(Projection::Type::IRREGULAR): |
|
{ |
|
out += "irregular, " + horCol + proj->N() + C() + " points"; |
|
break; |
|
} |
|
case(Projection::Type::IRREGULARXY): |
|
{ |
|
out += "irregular, " + horCol + proj->Nx() + C() + " x " + horCol + proj->Ny() + C() + " points, region (" + horCol + proj->Lon(0) + C() + " : " + horCol + |
|
proj->Lon(proj->Nx() - 1) + C() + ") x (" + horCol + proj->Lat(0) + C() + " : " + horCol + proj->Lat(proj->Ny() - 1) + C() + ")"; |
|
break; |
|
} |
|
case(Projection::Type::EQC): |
|
{ |
|
out += "rectangular, " + horCol + proj->Nx() + C() + " x " + horCol + proj->Ny() + C() + " points (" + horCol + (proj->Lon(proj->Nx() - 1) - proj->Lon(0)) / (proj->Nx() - 1) + |
|
C() + " x " + horCol + (proj->Lat(proj->Ny() - 1) - proj->Lat(0)) / (proj->Ny() - 1) + C() + "), region (" + horCol + proj->Lon(0) + C() + " : " + horCol + |
|
proj->Lon(proj->Nx() - 1) + C() + ") x (" + horCol + proj->Lat(0) + C() + " : " + horCol + proj->Lat(proj->Ny() - 1) + C() + ")"; |
|
break; |
|
} |
|
} |
|
message(out); |
|
usedproj[proj] = name; |
|
} |
|
} |
|
return ""; |
|
} |
|
|
|
template<class D> |
|
requires(!AdapterSupported<D> && InfoSupported<D>) |
|
MString ActionInfo_DoAction(const CLArgs& args, D& data) |
|
{ |
|
auto resop = data.Open(args); |
|
if(resop.Exist()) return "Can't open source: " + resop; |
|
auto info = data.Info(); |
|
if(!info.Exist()) return "No info"; |
|
message(info); |
|
return ""; |
|
};
|
|
|