34GribReader::GribReader() {
36 dewpointDataStatus = NO_DATA_IN_FILE;
39GribReader::GribReader(
const wxString fname) {
41 dewpointDataStatus = NO_DATA_IN_FILE;
42 if (fname != _T(
"")) {
49GribReader::~GribReader() {
51 if (file !=
nullptr) {
58void GribReader::clean_all_vectors() {
59 std::map<std::string, std::vector<GribRecord *> *>::iterator it;
60 for (it = mapGribRecords.begin(); it != mapGribRecords.end(); it++) {
61 std::vector<GribRecord *> *ls = (*it).second;
65 mapGribRecords.clear();
68void GribReader::clean_vector(std::vector<GribRecord *> &ls) {
69 std::vector<GribRecord *>::iterator it;
70 for (it = ls.begin(); it != ls.end(); it++) {
78void GribReader::storeRecordInMap(
GribRecord *rec) {
81 "GribReader: STORE record type: dataType=%d levelType=%d levelValue=%d idCenter==%d && idModel==%d && idGrid==%d\n",
86 std::map<std::string, std::vector<GribRecord *> *>::iterator it;
87 it = mapGribRecords.find(rec->getKey());
88 if (it == mapGribRecords.end()) {
89 mapGribRecords[rec->getKey()] =
new std::vector<GribRecord *>;
90 assert(mapGribRecords[rec->getKey()]);
92 mapGribRecords[rec->getKey()]->push_back(rec);
116void GribReader::readAllGribRecords() {
124 time_t firstdate = -1;
135 if (is_v2 ==
false) {
137 if (rec->isOk() ==
false) {
144 if (rec2 && rec2->hasMoreDataSet()) {
145 rec = rec2->GribV2NextDataSet(file,
id);
152 if (rec->isOk() ==
false) {
157 prevDataSet =
nullptr;
158 if (rec->isOk() ==
false) {
162 b_EOF = rec->isEof();
164 if (!rec->isDataKnown()) {
166 if (rec2 ==
nullptr || !rec2->hasMoreDataSet()) {
176 if (firstdate == -1) firstdate = rec->getRecordCurrentDate();
181 (RecordIsWind(rec) && rec->
getLevelType() == LV_ABOV_GND &&
183 (RecordIsWind(rec) &&
187 storeRecordInMap(rec);
189 else if ((RecordIsGust(rec) && rec->
getLevelType() == LV_GND_SURF &&
191 storeRecordInMap(rec);
193 else if (RecordIsWind(rec) && rec->
getLevelType() == LV_GND_SURF)
194 storeRecordInMap(rec);
198 storeRecordInMap(rec);
204 storeRecordInMap(rec);
208 storeRecordInMap(rec);
212 storeRecordInMap(rec);
217 storeRecordInMap(rec);
219 storeRecordInMap(rec);
223 storeRecordInMap(rec);
227 storeRecordInMap(rec);
230 storeRecordInMap(rec);
233 storeRecordInMap(rec);
236 storeRecordInMap(rec);
239 storeRecordInMap(rec);
244 storeRecordInMap(rec);
246 else if (RecordIsCurrent(rec))
247 storeRecordInMap(rec);
252 storeRecordInMap(rec);
259 storeRecordInMap(rec);
265 storeRecordInMap(rec);
271 "GribReader: unknown record type: dataType=%d levelType=%d levelValue=%d idCenter==%d && idModel==%d && idGrid==%d\n",
276 if (rec2 ==
nullptr || !rec2->hasMoreDataSet()) {
290 time_t dateref = getRefDate();
291 GribRecord *rec = getGribRecord(dataType, levelType, levelValue, dateref);
292 if (rec ==
nullptr) {
293 rec = getFirstGribRecord(dataType, levelType, levelValue);
294 if (rec !=
nullptr) {
296 r2->setRecordCurrentDate(dateref);
297 storeRecordInMap(r2);
325 std::set<time_t> setdates = getListDates();
326 std::set<time_t>::iterator itd, itd2;
327 for (itd = setdates.begin(); itd != setdates.end(); itd++) {
329 GribRecord *rec = getGribRecord(dataType, levelType, levelValue, date);
330 if (rec ==
nullptr) {
333 if (itd2 != setdates.end()) {
334 time_t date2 = *itd2;
336 getGribRecord(dataType, levelType, levelValue, date2);
337 if (rec2 && rec2->isOk()) {
340 r2->setRecordCurrentDate(date);
341 storeRecordInMap(r2);
348void GribReader::computeAccumulationRecords(
int dataType,
int levelType,
350 std::set<time_t> setdates = getListDates();
351 std::set<time_t>::reverse_iterator rit;
355 if (setdates.empty())
return;
358 for (rit = setdates.rbegin(); rit != setdates.rend(); ++rit) {
360 GribRecord *rec = getGribRecord(dataType, levelType, levelValue, date);
361 if (rec && rec->isOk()) {
370 prev->Substract(*rec);
381 prev->multiplyAllData(1.0 / (p2 - p1));
390 if (prev != 0 && p2 > p1 && prev->
getTimeRange() == 4) {
392 prev->multiplyAllData(1.0 / (p2 - p1));
423void GribReader::readGribFileContent() {
424 fileSize = zu_filesize(file);
425 readAllGribRecords();
429 if (getNumberOfGribRecords(GRB_WIND_GUST, LV_GND_SURF, 0) == 0) {
430 for (
auto date : setAllDates) {
431 GribRecord *recX = getGribRecord(GRB_WIND_GUST_VX, LV_GND_SURF, 0, date);
432 if (recX ==
nullptr)
continue;
434 GribRecord *recY = getGribRecord(GRB_WIND_GUST_VY, LV_GND_SURF, 0, date);
435 if (recY ==
nullptr)
continue;
436 GribRecord *rec = GribRecord::MagnitudeRecord(*recX, *recY);
437 rec->setDataType(GRB_WIND_GUST);
438 storeRecordInMap(rec);
445 dewpointDataStatus = DATA_IN_FILE;
446 if (getNumberOfGribRecords(GRB_DEWPOINT, LV_ABOV_GND, 2) != 0)
return;
448 dewpointDataStatus = NO_DATA_IN_FILE;
449 if (getNumberOfGribRecords(GRB_HUMID_REL, LV_ABOV_GND, 2) == 0 ||
450 getNumberOfGribRecords(GRB_TEMP, LV_ABOV_GND, 2) == 0)
453 dewpointDataStatus = COMPUTED_DATA;
454 for (
auto iter : setAllDates) {
456 GribRecord *recModel = getGribRecord(GRB_TEMP, LV_ABOV_GND, 2, date);
457 if (recModel ==
nullptr)
continue;
461 recDewpoint->setDataType(GRB_DEWPOINT);
462 for (zuint i = 0; i < (zuint)recModel->
getNi(); i++) {
463 for (zuint j = 0; j < (zuint)recModel->
getNj(); j++) {
465 recModel->
getXY(i, j, &x, &y);
466 double dp = computeDewPoint(x, y, date);
467 recDewpoint->setValue(i, j, dp);
470 storeRecordInMap(recDewpoint);
475int GribReader::getDewpointDataStatus(
int ,
int ) {
476 return dewpointDataStatus;
480int GribReader::getTotalNumberOfGribRecords() {
482 std::map<std::string, std::vector<GribRecord *> *>::iterator it;
483 for (it = mapGribRecords.begin(); it != mapGribRecords.end(); it++) {
484 nb += (*it).second->size();
490std::vector<GribRecord *> *GribReader::getFirstNonEmptyList() {
491 std::vector<GribRecord *> *ls =
nullptr;
492 std::map<std::string, std::vector<GribRecord *> *>::iterator it;
493 for (it = mapGribRecords.begin(); ls ==
nullptr && it != mapGribRecords.end();
495 if ((*it).second->size() > 0) ls = (*it).second;
501int GribReader::getNumberOfGribRecords(
int dataType,
int levelType,
503 std::vector<GribRecord *> *liste =
504 getListOfGribRecords(dataType, levelType, levelValue);
505 if (liste !=
nullptr)
506 return liste->size();
512std::vector<GribRecord *> *GribReader::getListOfGribRecords(
int dataType,
515 std::string key = GribRecord::makeKey(dataType, levelType, levelValue);
516 if (mapGribRecords.find(key) != mapGribRecords.end())
517 return mapGribRecords[key];
522double GribReader::getTimeInterpolatedValue(
int dataType,
int levelType,
523 int levelValue,
double px,
524 double py, time_t date) {
526 findGribsAroundDate(dataType, levelType, levelValue, date, &before, &after);
527 return get2GribsInterpolatedValueByDate(px, py, date, before, after);
531void GribReader::findGribsAroundDate(
int dataType,
int levelType,
532 int levelValue, time_t date,
535 std::vector<GribRecord *> *ls =
536 getListOfGribRecords(dataType, levelType, levelValue);
539 zuint nb = ls->size();
540 for (zuint i = 0; i < nb && *before ==
nullptr && *after ==
nullptr; i++) {
542 if (rec->getRecordCurrentDate() == date) {
545 }
else if (rec->getRecordCurrentDate() < date) {
547 }
else if (rec->getRecordCurrentDate() > date && *before !=
nullptr) {
554double GribReader::get2GribsInterpolatedValueByDate(
double px,
double py,
558 double val = GRIB_NOTDEF;
559 if (before !=
nullptr && after !=
nullptr) {
560 if (before == after) {
563 time_t t1 = before->getRecordCurrentDate();
564 time_t t2 = after->getRecordCurrentDate();
570 if (v1 != GRIB_NOTDEF && v2 != GRIB_NOTDEF) {
571 double k = fabs((
double)(date - t1) / (t2 - t1));
572 val = (1.0 - k) * v1 + k * v2;
583 std::vector<GribRecord *> *ls = getFirstNonEmptyList();
592GribRecord *GribReader::getFirstGribRecord(
int dataType,
int levelType,
594 std::set<time_t>::iterator it;
596 for (it = setAllDates.begin(); rec ==
nullptr && it != setAllDates.end();
599 rec = getGribRecord(dataType, levelType, levelValue, date);
607double GribReader::computeHoursBeetweenGribRecords() {
609 std::vector<GribRecord *> *ls = getFirstNonEmptyList();
611 time_t t0 = (*ls)[0]->getRecordCurrentDate();
612 time_t t1 = (*ls)[1]->getRecordCurrentDate();
613 res = fabs((
double)(t1 - t0)) / 3600.0;
614 if (res < 1) res = 1;
619GribRecord *GribReader::getGribRecord(
int dataType,
int levelType,
620 int levelValue, time_t date) {
621 std::vector<GribRecord *> *ls =
622 getListOfGribRecords(dataType, levelType, levelValue);
626 zuint nb = ls->size();
627 for (zuint i = 0; i < nb && res ==
nullptr; i++) {
628 if ((*ls)[i]->getRecordCurrentDate() == date) res = (*ls)[i];
638void GribReader::createListDates() {
641 std::map<std::string, std::vector<GribRecord *> *>::iterator it;
642 for (it = mapGribRecords.begin(); it != mapGribRecords.end(); it++) {
643 std::vector<GribRecord *> *ls = (*it).second;
644 for (zuint i = 0; i < ls->size(); i++) {
645 setAllDates.insert(ls->at(i)->getRecordCurrentDate());
651double GribReader::computeDewPoint(
double lon,
double lat, time_t now) {
652 double diewpoint = GRIB_NOTDEF;
654 GribRecord *recTempDiew = getGribRecord(GRB_DEWPOINT, LV_ABOV_GND, 2, now);
655 if (recTempDiew !=
nullptr) {
660 GribRecord *recTemp = getGribRecord(GRB_TEMP, LV_ABOV_GND, 2, now);
661 GribRecord *recHumid = getGribRecord(GRB_HUMID_REL, LV_ABOV_GND, 2, now);
662 if (recTemp && recHumid) {
665 if (temp != GRIB_NOTDEF && humid != GRIB_NOTDEF) {
668 double t = temp - 273.15;
672 double alpha = a * t / (b + t) + log(rh / 100.0);
673 diewpoint = b * alpha / (a - alpha);
685void GribReader::openFile(
const wxString fname) {
686 grib_debug(
"Open file: %s", (
const char *)fname.mb_str());
693 file = zu_open((
const char *)fname.mb_str(),
"rb", ZU_COMPRESS_AUTO);
694 if (file ==
nullptr) {
695 erreur(
"Can't open file: %s", (
const char *)fname.mb_str());
698 readGribFileContent();
702 if (file !=
nullptr) zu_close(file);
703 file = zu_open((
const char *)fname.mb_str(),
"rb", ZU_COMPRESS_BZIP);
704 if (file !=
nullptr) readGribFileContent();
707 if (file !=
nullptr) zu_close(file);
708 file = zu_open((
const char *)fname.mb_str(),
"rb", ZU_COMPRESS_GZIP);
709 if (file !=
nullptr) readGribFileContent();
712 if (file !=
nullptr) zu_close(file);
713 file = zu_open((
const char *)fname.mb_str(),
"rb", ZU_COMPRESS_NONE);
714 if (file !=
nullptr) readGribFileContent();
716 if (file !=
nullptr) {
GRIB (GRIdded Binary) file reader and parser.
GRIB Version 1 Record Implementation.
GRIB Version 2 Record Implementation.
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.
Represents a meteorological data grid from a GRIB (Gridded Binary) file.
zuchar getTimeRange() const
Returns the time range indicator that defines how P1 and P2 should be interpreted.
int getPeriodP1() const
Returns the start of the period (P1) used for this record.
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.
double getInterpolatedValue(double px, double py, bool numericalInterpolation=true, bool dir=false) const
Get spatially interpolated value at exact lat/lon position.
int getNi() const
Returns the number of points in the longitude (i) direction of the grid.
int getNj() const
Returns the number of points in the latitude (j) direction of the grid.
zuchar getIdGrid() const
Returns the grid definition template number.
zuint getLevelValue() const
Returns the numeric value associated with the level type.
zuchar getLevelType() const
Returns the type of vertical level for this grid's data.
zuchar getDataType() const
Returns the type of meteorological parameter stored in this grid.
zuchar getIdCenter() const
Returns the originating center ID as defined by WMO (World Meteorological Organization).