#define MICHLIB_NOSOURCE #include "BINFILE.h" MString BINFILEData::Info() const { if(!isOk()) return ""; michlib_internal::ParameterListEx pars; pars.AddParameters(data->DataFileParameters()); pars.UsePrefix("Datafile_Info"); MString title = pars.ParameterSValue("DataSource", "no information"); MString lonb = pars.ParameterSValue("lonb", ""); MString lone = pars.ParameterSValue("lone", ""); MString latb = pars.ParameterSValue("latb", ""); MString late = pars.ParameterSValue("late", ""); MString dataid = pars.ParameterSValue("DataID", "no information"); // clang-format off return "Dataset: " + title + "\n" + " DataId: " + dataid + "\n" + " Begin date: " + Time(0).ToString() + "\n" + " End date: " + Time(NTimes()-1).ToString() + "\n" + " Time step: " + Timestep() + " seconds\n" + " Time moments: " + NTimes() + "\n" + " Region: (" + lonb + " : " + lone + ") x (" + latb + " : " + late + ")\n" + " Grid: " + data->Nx() + "x" + data->Ny() + "\n" + " Supported variables: u, v, U2"; // clang-format on } MString BINFILEData::Open(const CLArgs& args) { GPL.UsePrefix("BINFILE"); datapath = GPL.ParameterSValue("Datapath", ""); MString dataset = args.contains("dataset") ? args.at("dataset") : ""; if(!dataset.Exist()) return "No data file"; MString file; { RegExp regex("^[0-9a-f]{64}$"); regex.Compile(); if(regex.Match(dataset.Buf())) file = michlib::FindFileByID(datapath, dataset); else file = (dataset[0] != '/') ? (datapath + "/" + dataset) : dataset; } data.reset(new michlib::IntData); if(!data->Open(file)) return "Can't open file " + file; for(size_t it = 0; it < data->Nt(); it++) times.push_back(data->Date(it)); return ""; } bool BINFILEData::Read(const MString& vname, std::map& cache, size_t i) const { if(cache.contains(vname)) return true; if(!isOk()) return false; // Only rectangular grids are supported real xs = (data->Lon(data->Nx() - 1, data->Ny() - 1) - data->Lon(0, 0)) / (data->Nx() - 1); real ys = (data->Lat(data->Nx() - 1, data->Ny() - 1) - data->Lat(0, 0)) / (data->Ny() - 1); Data out(data->Nx(), data->Ny(), data->Lon(0, 0), data->Lat(0, 0), xs, ys, "cm/s"); // TODO: Information about unit must be taken from datafile // U and U2 from u and v if(vname == "U" || vname == "U2") { bool square = vname == "U2"; if(!(Read("u", cache, i) && Read("v", cache, i))) return false; cache[vname] = cache.at("u").CopyGrid(); auto& U = cache.at(vname); const auto& u = cache.at("u"); const auto& v = cache.at("v"); if(u.Unit().Exist()) U.SetUnit(square ? ("(" + u.Unit() + ")2") : u.Unit()); for(size_t ind = 0; ind < U.N(); ind++) { if(u.IsFill(ind) || v.IsFill(ind)) U.V(ind) = U.Fillval(); else U.V(ind) = square ? (u(ind) * u(ind) + v(ind) * v(ind)) : michlib::Hypot(u(ind), v(ind)); } return true; } if(vname == "u" || vname == "v") { bool isu = vname == "u"; for(size_t ix = 0; ix < data->Nx(); ix++) for(size_t iy = 0; iy < data->Ny(); iy++) { if(data->IsOk(ix, iy, i)) out.V(ix, iy) = isu ? data->Ur(ix, iy, i) : data->Vr(ix, iy, i); else out.V(ix, iy) = out.Fillval(); } if(out) { cache[vname] = std::move(out); return true; } } return false; }