|
|
|
@ -1,12 +1,154 @@
|
|
|
|
|
#pragma once |
|
|
|
|
#include "CF.h" |
|
|
|
|
#include "actiondep.h" |
|
|
|
|
#include "merrors.h" |
|
|
|
|
|
|
|
|
|
using michlib::message; |
|
|
|
|
using michlib::uint2; |
|
|
|
|
|
|
|
|
|
ADD_ACTION(Info, info, InfoSupported<Source>); |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
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()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
// Header
|
|
|
|
|
message(titCol, ad.Title(), C()); |
|
|
|
|
{ |
|
|
|
|
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); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 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.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; |
|
|
|
|