37GribReader::GribReader() {
39 dewpointDataStatus = NO_DATA_IN_FILE;
42GribReader::GribReader(
const wxString fname) {
44 dewpointDataStatus = NO_DATA_IN_FILE;
52GribReader::~GribReader() {
54 if (file !=
nullptr) {
61void GribReader::CleanAllVectors() {
62 std::map<std::string, std::vector<GribRecord *> *>::iterator it;
63 for (it = mapGribRecords.begin(); it != mapGribRecords.end(); it++) {
64 std::vector<GribRecord *> *ls = (*it).second;
68 mapGribRecords.clear();
71void GribReader::CleanVector(std::vector<GribRecord *> &ls) {
72 std::vector<GribRecord *>::iterator it;
73 for (it = ls.begin(); it != ls.end(); it++) {
81void GribReader::storeRecordInMap(
GribRecord *rec) {
84 "GribReader: STORE record type: data_type=%d level_type=%d level_value=%d idCenter==%d && idModel==%d && idGrid==%d\n",
89 std::map<std::string, std::vector<GribRecord *> *>::iterator it;
90 it = mapGribRecords.find(rec->GetKey());
91 if (it == mapGribRecords.end()) {
92 mapGribRecords[rec->GetKey()] =
new std::vector<GribRecord *>;
93 assert(mapGribRecords[rec->GetKey()]);
95 mapGribRecords[rec->GetKey()]->push_back(rec);
119void GribReader::ReadAllGribRecords() {
127 time_t firstdate = -1;
138 if (is_v2 ==
false) {
140 if (rec->IsOk() ==
false) {
147 if (rec2 && rec2->hasMoreDataSet()) {
148 rec = rec2->GribV2NextDataSet(file,
id);
155 if (rec->IsOk() ==
false) {
160 prevDataSet =
nullptr;
161 if (rec->IsOk() ==
false) {
165 b_EOF = rec->IsEof();
167 if (!rec->IsDataKnown()) {
169 if (rec2 ==
nullptr || !rec2->hasMoreDataSet()) {
179 if (firstdate == -1) firstdate = rec->GetRecordCurrentDate();
184 (RecordIsWind(rec) && rec->
GetLevelType() == LV_ABOV_GND &&
186 (RecordIsWind(rec) &&
190 storeRecordInMap(rec);
192 else if ((RecordIsGust(rec) && rec->
GetLevelType() == LV_GND_SURF &&
194 storeRecordInMap(rec);
196 else if (RecordIsWind(rec) && rec->
GetLevelType() == LV_GND_SURF)
197 storeRecordInMap(rec);
201 storeRecordInMap(rec);
207 storeRecordInMap(rec);
211 storeRecordInMap(rec);
215 storeRecordInMap(rec);
220 storeRecordInMap(rec);
222 storeRecordInMap(rec);
226 storeRecordInMap(rec);
230 storeRecordInMap(rec);
233 storeRecordInMap(rec);
236 storeRecordInMap(rec);
239 storeRecordInMap(rec);
242 storeRecordInMap(rec);
247 storeRecordInMap(rec);
249 else if (RecordIsCurrent(rec))
250 storeRecordInMap(rec);
255 storeRecordInMap(rec);
262 storeRecordInMap(rec);
268 storeRecordInMap(rec);
274 "GribReader: unknown record type: data_type=%d level_type=%d level_value=%d idCenter==%d && idModel==%d && idGrid==%d\n",
279 if (rec2 ==
nullptr || !rec2->hasMoreDataSet()) {
293 time_t dateref = GetRefDate();
294 GribRecord *rec = GetGribRecord(dataType, levelType, levelValue, dateref);
295 if (rec ==
nullptr) {
296 rec = GetFirstGribRecord(dataType, levelType, levelValue);
297 if (rec !=
nullptr) {
299 r2->SetRecordCurrentDate(dateref);
300 storeRecordInMap(r2);
328 std::set<time_t> setdates = GetListDates();
329 std::set<time_t>::iterator itd, itd2;
330 for (itd = setdates.begin(); itd != setdates.end(); itd++) {
332 GribRecord *rec = GetGribRecord(dataType, levelType, levelValue, date);
333 if (rec ==
nullptr) {
336 if (itd2 != setdates.end()) {
337 time_t date2 = *itd2;
339 GetGribRecord(dataType, levelType, levelValue, date2);
340 if (rec2 && rec2->IsOk()) {
343 r2->SetRecordCurrentDate(date);
344 storeRecordInMap(r2);
351void GribReader::ComputeAccumulationRecords(
int dataType,
int levelType,
353 std::set<time_t> setdates = GetListDates();
354 std::set<time_t>::reverse_iterator rit;
358 if (setdates.empty())
return;
361 for (rit = setdates.rbegin(); rit != setdates.rend(); ++rit) {
363 GribRecord *rec = GetGribRecord(dataType, levelType, levelValue, date);
364 if (rec && rec->IsOk()) {
373 prev->Substract(*rec);
384 prev->multiplyAllData(1.0 / (p2 - p1));
393 if (prev != 0 && p2 > p1 && prev->
GetTimeRange() == 4) {
395 prev->multiplyAllData(1.0 / (p2 - p1));
426void GribReader::ReadGribFileContent() {
427 fileSize = zu_filesize(file);
428 ReadAllGribRecords();
432 if (GetNumberOfGribRecords(GRB_WIND_GUST, LV_GND_SURF, 0) == 0) {
433 for (
auto date : SetAllDates) {
434 GribRecord *recX = GetGribRecord(GRB_WIND_GUST_VX, LV_GND_SURF, 0, date);
435 if (recX ==
nullptr)
continue;
437 GribRecord *recY = GetGribRecord(GRB_WIND_GUST_VY, LV_GND_SURF, 0, date);
438 if (recY ==
nullptr)
continue;
439 GribRecord *rec = GribRecord::MagnitudeRecord(*recX, *recY);
440 rec->SetDataType(GRB_WIND_GUST);
441 storeRecordInMap(rec);
448 dewpointDataStatus = DATA_IN_FILE;
449 if (GetNumberOfGribRecords(GRB_DEWPOINT, LV_ABOV_GND, 2) != 0)
return;
451 dewpointDataStatus = NO_DATA_IN_FILE;
452 if (GetNumberOfGribRecords(GRB_HUMID_REL, LV_ABOV_GND, 2) == 0 ||
453 GetNumberOfGribRecords(GRB_TEMP, LV_ABOV_GND, 2) == 0)
456 dewpointDataStatus = COMPUTED_DATA;
457 for (
auto iter : SetAllDates) {
459 GribRecord *recModel = GetGribRecord(GRB_TEMP, LV_ABOV_GND, 2, date);
460 if (recModel ==
nullptr)
continue;
464 recDewpoint->SetDataType(GRB_DEWPOINT);
465 for (zuint i = 0; i < (zuint)recModel->
GetNi(); i++) {
466 for (zuint j = 0; j < (zuint)recModel->
GetNj(); j++) {
468 recModel->
getXY(i, j, &x, &y);
469 double dp = ComputeDewPoint(x, y, date);
470 recDewpoint->SetValue(i, j, dp);
473 storeRecordInMap(recDewpoint);
478int GribReader::GetDewpointDataStatus(
int ,
int ) {
479 return dewpointDataStatus;
483int GribReader::GetTotalNumberOfGribRecords() {
485 std::map<std::string, std::vector<GribRecord *> *>::iterator it;
486 for (it = mapGribRecords.begin(); it != mapGribRecords.end(); it++) {
487 nb += (*it).second->size();
493std::vector<GribRecord *> *GribReader::GetFirstNonEmptyList() {
494 std::vector<GribRecord *> *ls =
nullptr;
495 std::map<std::string, std::vector<GribRecord *> *>::iterator it;
496 for (it = mapGribRecords.begin(); ls ==
nullptr && it != mapGribRecords.end();
498 if ((*it).second->size() > 0) ls = (*it).second;
504int GribReader::GetNumberOfGribRecords(
int dataType,
int levelType,
506 std::vector<GribRecord *> *liste =
507 getListOfGribRecords(dataType, levelType, levelValue);
508 if (liste !=
nullptr)
509 return liste->size();
515std::vector<GribRecord *> *GribReader::getListOfGribRecords(
int dataType,
518 std::string key = GribRecord::MakeKey(dataType, levelType, levelValue);
519 if (mapGribRecords.find(key) != mapGribRecords.end())
520 return mapGribRecords[key];
525double GribReader::GetTimeInterpolatedValue(
int dataType,
int levelType,
526 int levelValue,
double px,
527 double py, time_t date) {
529 FindGribsAroundDate(dataType, levelType, levelValue, date, &before, &after);
530 return Get2GribsInterpolatedValueByDate(px, py, date, before, after);
534void GribReader::FindGribsAroundDate(
int dataType,
int levelType,
535 int levelValue, time_t date,
538 std::vector<GribRecord *> *ls =
539 getListOfGribRecords(dataType, levelType, levelValue);
542 zuint nb = ls->size();
543 for (zuint i = 0; i < nb && *before ==
nullptr && *after ==
nullptr; i++) {
545 if (rec->GetRecordCurrentDate() == date) {
548 }
else if (rec->GetRecordCurrentDate() < date) {
550 }
else if (rec->GetRecordCurrentDate() > date && *before !=
nullptr) {
557double GribReader::Get2GribsInterpolatedValueByDate(
double px,
double py,
561 double val = GRIB_NOTDEF;
562 if (before !=
nullptr && after !=
nullptr) {
563 if (before == after) {
566 time_t t1 = before->GetRecordCurrentDate();
567 time_t t2 = after->GetRecordCurrentDate();
573 if (v1 != GRIB_NOTDEF && v2 != GRIB_NOTDEF) {
574 double k = fabs((
double)(date - t1) / (t2 - t1));
575 val = (1.0 - k) * v1 + k * v2;
586 std::vector<GribRecord *> *ls = GetFirstNonEmptyList();
595GribRecord *GribReader::GetFirstGribRecord(
int dataType,
int levelType,
597 std::set<time_t>::iterator it;
599 for (it = SetAllDates.begin(); rec ==
nullptr && it != SetAllDates.end();
602 rec = GetGribRecord(dataType, levelType, levelValue, date);
610double GribReader::ComputeHoursBeetweenGribRecords() {
612 std::vector<GribRecord *> *ls = GetFirstNonEmptyList();
614 time_t t0 = (*ls)[0]->GetRecordCurrentDate();
615 time_t t1 = (*ls)[1]->GetRecordCurrentDate();
616 res = fabs((
double)(t1 - t0)) / 3600.0;
617 if (res < 1) res = 1;
622GribRecord *GribReader::GetGribRecord(
int dataType,
int levelType,
623 int levelValue, time_t date) {
624 std::vector<GribRecord *> *ls =
625 getListOfGribRecords(dataType, levelType, levelValue);
629 zuint nb = ls->size();
630 for (zuint i = 0; i < nb && res ==
nullptr; i++) {
631 if ((*ls)[i]->GetRecordCurrentDate() == date) res = (*ls)[i];
641void GribReader::CreateListDates() {
644 std::map<std::string, std::vector<GribRecord *> *>::iterator it;
645 for (it = mapGribRecords.begin(); it != mapGribRecords.end(); it++) {
646 std::vector<GribRecord *> *ls = (*it).second;
647 for (zuint i = 0; i < ls->size(); i++) {
648 SetAllDates.insert(ls->at(i)->GetRecordCurrentDate());
654double GribReader::ComputeDewPoint(
double lon,
double lat, time_t now) {
655 double diewpoint = GRIB_NOTDEF;
657 GribRecord *recTempDiew = GetGribRecord(GRB_DEWPOINT, LV_ABOV_GND, 2, now);
658 if (recTempDiew !=
nullptr) {
663 GribRecord *recTemp = GetGribRecord(GRB_TEMP, LV_ABOV_GND, 2, now);
664 GribRecord *recHumid = GetGribRecord(GRB_HUMID_REL, LV_ABOV_GND, 2, now);
665 if (recTemp && recHumid) {
668 if (temp != GRIB_NOTDEF && humid != GRIB_NOTDEF) {
671 double t = temp - 273.15;
675 double alpha = a * t / (b + t) + log(rh / 100.0);
676 diewpoint = b * alpha / (a - alpha);
688void GribReader::OpenFile(
const wxString fname) {
689 grib_debug(
"Open file: %s", (
const char *)fname.mb_str());
696 file = zu_open((
const char *)fname.mb_str(),
"rb", ZU_COMPRESS_AUTO);
697 if (file ==
nullptr) {
698 erreur(
"Can't open file: %s", (
const char *)fname.mb_str());
701 ReadGribFileContent();
705 if (file !=
nullptr) zu_close(file);
706 file = zu_open((
const char *)fname.mb_str(),
"rb", ZU_COMPRESS_BZIP);
707 if (file !=
nullptr) ReadGribFileContent();
710 if (file !=
nullptr) zu_close(file);
711 file = zu_open((
const char *)fname.mb_str(),
"rb", ZU_COMPRESS_GZIP);
712 if (file !=
nullptr) ReadGribFileContent();
715 if (file !=
nullptr) zu_close(file);
716 file = zu_open((
const char *)fname.mb_str(),
"rb", ZU_COMPRESS_NONE);
717 if (file !=
nullptr) ReadGribFileContent();
719 if (file !=
nullptr) {
void CopyMissingWaveRecords()
Fills gaps in wave-related data fields by propagating known values across missing time periods.
void CopyFirstCumulativeRecord()
Initializes cumulative meteorological parameters by copying their first record values.
A meteorological data grid from a GRIB (Gridded Binary) file.
int GetNj() const
Returns the number of points in the latitude (j) direction of the grid.
zuchar GetTimeRange() const
Returns the time range indicator that defines how P1 and P2 should be interpreted.
void getXY(int i, int j, double *x, double *y) const
Converts grid indices to longitude/latitude coordinates.
zuchar GetIdModel() const
Returns the model/process ID within the originating center.
int GetPeriodP2() const
Returns the end of the period (P2) used for this record.
zuchar GetDataType() const
Returns the type of meteorological parameter stored in this grid.
double GetInterpolatedValue(double px, double py, bool numericalInterpolation=true, bool dir=false) const
Get spatially interpolated value at exact lat/lon position.
zuchar GetIdCenter() const
Returns the originating center ID as defined by WMO (World Meteorological Organization).
int GetPeriodP1() const
Returns the start of the period (P1) used for this record.
int GetNi() const
Returns the number of points in the longitude (i) direction of the grid.
zuint GetLevelValue() const
Returns the numeric value associated with the level type.
zuchar GetIdGrid() const
Returns the grid definition template number.
zuchar GetLevelType() const
Returns the type of vertical level for this grid's data.
GRIB (GRIdded Binary) file reader and parser.
GRIB Version 1 Record Implementation.
GRIB Version 2 Record Implementation.