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.
 
 
 

284 lines
10 KiB

#define MICHLIB_NOSOURCE
#include "ncfuncs.h"
NCFuncs::CoordNames NCFuncs::GetDNames(const NCFileA& nc)
{
CoordNames out;
auto head = nc.Header();
for(const auto& dim: head.Dimensions())
{
if(dim.Name() == "lon" || dim.Name() == "longitude")
{
out.lonname = dim.Name();
out.nx = dim.Len();
}
if(dim.Name() == "lat" || dim.Name() == "latitude")
{
out.latname = dim.Name();
out.ny = dim.Len();
}
if(dim.Name() == "depth")
{
out.depthname = dim.Name();
out.nz = dim.Len();
}
if(dim.Name() == "time")
{
out.timename = dim.Name();
out.nt = dim.Len();
}
}
return out;
}
NCFuncs::CoordNames NCFuncs::GetDNames(const NCZarr& nc)
{
CoordNames out;
for(const auto& dim: nc.Dims())
{
if(dim.Name() == "lon" || dim.Name() == "longitude")
{
out.lonname = dim.Name();
out.nx = dim.Size();
}
if(dim.Name() == "lat" || dim.Name() == "latitude")
{
out.latname = dim.Name();
out.ny = dim.Size();
}
if(dim.Name() == "depth" || dim.Name() == "elevation")
{
out.depthname = dim.Name();
out.nz = dim.Size();
}
if(dim.Name() == "time")
{
out.timename = dim.Name();
out.nt = dim.Size();
}
}
return out;
}
NCFuncs::CoordNames NCFuncs::GetCNames(const NCFileA& nc)
{
CoordNames out;
auto head = nc.Header();
for(const auto& v: head.Variables()) // Try to define coordinates by attribute standard_name or attribute axis
{
auto stname = nc.A<MString>(v.Name(), "standard_name");
auto axis = nc.A<MString>(v.Name(), "axis");
bool islon = false, islat = false, isdepth = false, istime = false;
if(!(stname || axis)) continue;
if(stname && stname.Get() == "longitude") islon = true;
if(stname && stname.Get() == "latitude") islat = true;
if(stname && stname.Get() == "depth") isdepth = true;
if(stname && stname.Get() == "time") istime = true;
if(!out.lonname.Exist() && axis && axis.Get() == "X") islon = true;
if(!out.latname.Exist() && axis && axis.Get() == "Y") islat = true;
if(!out.depthname.Exist() && axis && axis.Get() == "Z") isdepth = true;
if(!out.timename.Exist() && axis && axis.Get() == "T") istime = true;
if(islon) out.lonname = v.Name();
if(islat) out.latname = v.Name();
if(isdepth) out.depthname = v.Name();
if(istime) out.timename = v.Name();
if(islon) out.nx = v.Dimensions().size();
if(islat) out.ny = v.Dimensions().size();
if(isdepth) out.nz = v.Dimensions().size();
if(istime) out.nt = v.Dimensions().size();
}
return out;
}
NCFuncs::CoordNames NCFuncs::GetCNames(const NCZarr& nc)
{
CoordNames out;
for(const auto& v: nc.Vars()) // Try to define coordinates by attribute standard_name or attribute axis
{
auto havestname = nc.HasAtt(v.Name(), "standard_name");
auto haveaxis = nc.HasAtt(v.Name(), "axis");
if(!(havestname || haveaxis)) continue;
auto stname = nc.AttString(v.Name(), "standard_name");
auto axis = nc.AttString(v.Name(), "axis");
bool islon = false, islat = false, isdepth = false, istime = false;
if(stname == "longitude") islon = true;
if(stname == "latitude") islat = true;
if(stname == "depth") isdepth = true;
if(stname == "time") istime = true;
if(!out.lonname.Exist() && axis == "X") islon = true;
if(!out.latname.Exist() && axis == "Y") islat = true;
if(!out.depthname.Exist() && axis == "Z") isdepth = true;
if(!out.timename.Exist() && axis == "T") istime = true;
if(islon) out.lonname = v.Name();
if(islat) out.latname = v.Name();
if(isdepth) out.depthname = v.Name();
if(istime) out.timename = v.Name();
if(islon) out.nx = v.Dims().size();
if(islat) out.ny = v.Dims().size();
if(isdepth) out.nz = v.Dims().size();
if(istime) out.nt = v.Dims().size();
}
// If time not found just check variable "time"
if(!out.timename.Exist() && nc.HasVar("time")) out.timename = "time";
return out;
}
void NCFuncs::GetVars(const NCFileA& nc, std::set<MString>& vars)
{
auto head = nc.Header();
for(const auto& v: head.Variables())
{
auto ret = nc.A<MString>(v.Name(), "standard_name");
if(!ret) continue;
if(StName2Name(ret).Exist()) vars.emplace(StName2Name(ret));
}
if((vars.contains("ptemp") || vars.contains("temp")) && vars.contains("sal")) vars.emplace("pdens");
if(vars.contains("ptemp") && vars.contains("sal")) vars.emplace("temp");
if(vars.contains("temp") && vars.contains("sal")) vars.emplace("ptemp");
if(vars.contains("u") && vars.contains("v")) vars.emplace("U");
if(vars.contains("u") && vars.contains("v")) vars.emplace("U2");
if(vars.contains("ssh")) vars.emplace("ugeo");
if(vars.contains("ssh")) vars.emplace("vgeo");
}
void NCFuncs::GetVars(const NCZarr& nc, std::set<MString>& vars)
{
for(const auto& v: nc.Vars())
{
if(!nc.HasAtt(v.Name(), "standard_name")) continue;
auto ret = nc.AttString(v.Name(), "standard_name");
if(StName2Name(ret).Exist()) vars.emplace(StName2Name(ret));
}
if((vars.contains("ptemp") || vars.contains("temp")) && vars.contains("sal")) vars.emplace("pdens");
if(vars.contains("ptemp") && vars.contains("sal")) vars.emplace("temp");
if(vars.contains("temp") && vars.contains("sal")) vars.emplace("ptemp");
if(vars.contains("u") && vars.contains("v")) vars.emplace("U");
if(vars.contains("u") && vars.contains("v")) vars.emplace("U2");
if(vars.contains("ssh")) vars.emplace("ugeo");
if(vars.contains("ssh")) vars.emplace("vgeo");
}
std::tuple<MDateTime, time_t, bool> NCFuncs::Refdate(const MString& refdate)
{
MDateTime out;
time_t step = 0;
MString rstr;
auto words = michlib::Split_on_words(refdate);
auto ci = words.begin();
if(ci != words.end())
{
if(*ci == "seconds") step = 1;
if(*ci == "minutes") step = 60;
if(*ci == "hours") step = 3600;
if(*ci == "days") step = 3600 * 24;
ci++;
}
if(ci != words.end()) ci++; // skip "since"
if(ci != words.end()) rstr = *ci; // Day
if(ci != words.end()) ci++;
if(ci != words.end()) rstr += " " + *ci; // Hours
bool success = out.FromString(rstr);
return {out, step, success};
}
MString NCFuncs::StName2Name(const MString& stname)
{
if(stname == "sea_water_potential_temperature") return "ptemp";
if(stname == "sea_water_temperature") return "temp";
if(stname == "sea_water_salinity") return "sal";
if(stname == "ocean_mixed_layer_thickness_defined_by_sigma_theta") return "mld";
if(stname == "sea_surface_height_above_geoid") return "ssh";
if(stname == "sea_surface_elevation") return "ssh";
if(stname == "eastward_sea_water_velocity") return "u";
if(stname == "northward_sea_water_velocity") return "v";
if(stname == "upward_sea_water_velocity") return "w";
if(stname == "surface_geostrophic_eastward_sea_water_velocity") return "ugs";
if(stname == "surface_geostrophic_northward_sea_water_velocity") return "vgs";
if(stname == "mass_concentration_of_chlorophyll_a_in_sea_water") return "chl";
if(stname == "mole_concentration_of_nitrate_in_sea_water") return "NO3";
if(stname == "net_primary_production_of_biomass_expressed_as_carbon_per_unit_volume_in_sea_water") return "prprod";
if(stname == "mole_concentration_of_phytoplankton_expressed_as_carbon_in_sea_water") return "Cchl";
if(stname == "mole_concentration_of_phosphate_in_sea_water") return "PO4";
if(stname == "mole_concentration_of_silicate_in_sea_water") return "Si";
return "";
}
MString NCFuncs::Name2StName(const MString& name)
{
if(name == "ptemp") return "sea_water_potential_temperature";
if(name == "temp") return "sea_water_temperature";
if(name == "sal") return "sea_water_salinity";
if(name == "mld") return "ocean_mixed_layer_thickness_defined_by_sigma_theta";
if(name == "ssh") return "sea_surface_height_above_geoid";
if(name == "u") return "eastward_sea_water_velocity";
if(name == "v") return "northward_sea_water_velocity";
if(name == "w") return "upward_sea_water_velocity";
if(name == "ugs") return "surface_geostrophic_eastward_sea_water_velocity";
if(name == "vgs") return "surface_geostrophic_northward_sea_water_velocity";
if(name == "chl") return "mass_concentration_of_chlorophyll_a_in_sea_water";
if(name == "NO3") return "mole_concentration_of_nitrate_in_sea_water";
if(name == "prprod") return "net_primary_production_of_biomass_expressed_as_carbon_per_unit_volume_in_sea_water";
if(name == "Cchl") return "mole_concentration_of_phytoplankton_expressed_as_carbon_in_sea_water";
if(name == "PO4") return "mole_concentration_of_phosphate_in_sea_water";
if(name == "Si") return "mole_concentration_of_silicate_in_sea_water";
return "";
}
MString NCFuncs::Name2LongName(const MString& name)
{
if(name == "ptemp") return "Potential temperature";
if(name == "temp") return "Temperature";
if(name == "sal") return "Salinity";
if(name == "mld") return "Mixed layer depth";
if(name == "ssh") return "Sea surface height";
if(name == "u") return "X-velocity";
if(name == "v") return "Y-velocity";
if(name == "w") return "Z-velocity";
if(name == "ugeo") return "Geostrophic eastward velocity from ssh";
if(name == "vgeo") return "Geostrophic northward velocity from ssh";
if(name == "ugs") return "Geostrophic eastward velocity";
if(name == "vgs") return "Geostrophic northward velocity";
if(name == "chl") return "Concentration of chlorophyll";
if(name == "NO3") return "Concentration of nitrates";
if(name == "prprod") return "Primary production";
if(name == "Cchl") return "Concentration of chlorophyll carbon";
if(name == "PO4") return "Concentration of phosphates";
if(name == "Si") return "Concentration of silicates";
if(name == "U") return "Module of horizontal velocity";
if(name == "U2") return "Squared horizontal velocity";
return "";
}
bool NCFuncs::HaveVar(const NCFileA& nc, const MString& vname)
{
auto head = nc.Header();
for(const auto& v: head.Variables())
{
auto stname = nc.A<MString>(v.Name(), "standard_name");
if(!stname) continue;
if(StName2Name(stname) == vname) return true;
}
return false;
}
bool NCFuncs::HaveVar(const NCZarr& nc, const MString& vname)
{
for(const auto& v: nc.Vars())
{
if(!nc.HasAtt(v.Name(), "standard_name")) continue;
auto stname = nc.AttString(v.Name(), "standard_name");
if(StName2Name(stname) == vname) return true;
}
return false;
}