ECC-991: Add the local lat/lon keys

This commit is contained in:
Shahram Najm 2019-09-26 18:29:30 +01:00
parent 184ff8258c
commit eee9d9773a
4 changed files with 214 additions and 48 deletions

View File

@ -141,9 +141,6 @@ static int bufr_extract_edition(const void* message, long* edition)
/* The ECMWF BUFR local use section */
static int bufr_decode_rdb_keys(const void* message, long offset_section2, codes_bufr_header* hdr)
{
const long nbits_section2Length = 3*8;
long pos_section2Length = offset_section2*8;
long nbits_rdbType = 1*8;
long pos_rdbType = (offset_section2+4)*8;
long nbits_oldSubtype = 1*8;
@ -165,7 +162,6 @@ static int bufr_decode_rdb_keys(const void* message, long offset_section2, codes
DebugAssert(hdr->localSectionPresent);
hdr->section2Length = grib_decode_unsigned_long(message, &pos_section2Length, nbits_section2Length);
hdr->rdbType = (long)grib_decode_unsigned_long(message, &pos_rdbType, nbits_rdbType);
hdr->oldSubtype = (long)grib_decode_unsigned_long(message, &pos_oldSubtype, nbits_oldSubtype);
@ -204,16 +200,14 @@ static int bufr_decode_rdb_keys(const void* message, long offset_section2, codes
static int bufr_decode_extra_rdb_keys(const void* message, long offset_section2, codes_bufr_header* hdr)
{
size_t i = 0;
int isSatelliteType = 0;
int isSatellite = 0;
long start = 0;
const long offset_keyData = offset_section2 + 6;
const long offset_keyMore = offset_section2 + 19; /* 8 bytes long */
const long offset_keySat = offset_section2 + 27; /* 9 bytes long */
/*const long offset_keyData = offset_section2 + 6;*/
const long offset_keyMore = offset_section2 + 19;
/*const long offset_keySat = offset_section2 + 27;*/
/*unsigned char* p = (unsigned char*)message + offset_keyData;*/
char* q = (char*)message + offset_keyMore;
unsigned char* pKeyData = (unsigned char*)message + offset_keyData;
char* pKeyMore = (char*)message + offset_keyMore;
DebugAssert(hdr->localSectionPresent);
@ -221,15 +215,57 @@ static int bufr_decode_extra_rdb_keys(const void* message, long offset_section2,
isSatelliteType = 1;
}
if (isSatelliteType || hdr->numberOfSubsets > 1) {
isSatellite = 1;
hdr->isSatellite = 1;
} else {
isSatellite = 0;
hdr->isSatellite = 0;
}
if (hdr->isSatellite) {
unsigned char* pKeyMoreLong = (unsigned char*)message + offset_keyMore; /* as an integer */
unsigned char* pKeySat = (unsigned char*)message + offset_keySat;
long lValue = 0;
start = 40;
lValue = (long)grib_decode_unsigned_long(pKeyData, &start, 26);
hdr->localLongitude1 = (lValue - 18000000.0)/100000.0;
start = 72;
lValue = (long)grib_decode_unsigned_long(pKeyData, &start, 25);
hdr->localLatitude1 = (lValue - 9000000.0)/100000.0;
start = 0;
lValue = (long)grib_decode_unsigned_long(pKeyMoreLong, &start, 26);
hdr->localLongitude2 = (lValue -18000000.0)/100000.0;
start = 32;
lValue = (long)grib_decode_unsigned_long(pKeyMoreLong, &start, 25);
hdr->localLatitude2 = (lValue - 9000000)/100000.0;
if (hdr->oldSubtype == 255 || hdr->numberOfSubsets > 255 ||
(hdr->oldSubtype >= 121 && hdr->oldSubtype <= 130) ||
hdr->oldSubtype==31)
{
start = 0;
hdr->localNumberOfObservations = (long)grib_decode_unsigned_long(pKeySat, &start, 16);
start = 16;
hdr->satelliteID = (long)grib_decode_unsigned_long(pKeySat, &start, 16);
}
else
{
start = 0;
hdr->localNumberOfObservations = (long)grib_decode_unsigned_long(pKeySat, &start, 8);
start = 8;
hdr->satelliteID = (long)grib_decode_unsigned_long(pKeySat, &start, 16);
}
}
else {
long lValue = 0;
start = 72;
lValue = (long)grib_decode_unsigned_long(pKeyData, &start, 25);
hdr->localLatitude = (lValue -9000000.0)/100000.0;
start = 40;
lValue = (long)grib_decode_unsigned_long(pKeyData, &start, 26);
hdr->localLongitude = (lValue - 18000000.0)/100000.0;
if (!isSatellite) {
/* interpret keyMore as a string */
for (i=0; i<8; ++i) {
hdr->ident[i] = *q++;
hdr->ident[i] = *pKeyMore++;
}
hdr->ident[i] = '\0';
}
@ -260,6 +296,7 @@ static int bufr_decode_edition3(const void* message, codes_bufr_header* hdr)
long nbits_updateSequenceNumber = 1*8;
long pos_updateSequenceNumber = 14*8;
long section1Flags = 0;
long nbits_section1Flags = 1*8;
long pos_section1Flags = 15*8;
@ -290,6 +327,7 @@ static int bufr_decode_edition3(const void* message, codes_bufr_header* hdr)
long nbits_typicalMinute = 1*8;
long pos_typicalMinute = 24*8;
long section2Length = 0;
long offset_section2 = 0;
long offset_section3 = 0;
long nbits_numberOfSubsets = 2*8;
@ -305,7 +343,7 @@ static int bufr_decode_edition3(const void* message, codes_bufr_header* hdr)
hdr->bufrHeaderSubCentre = (long)grib_decode_unsigned_long(message, &pos_bufrHeaderSubCentre, nbits_bufrHeaderSubCentre);
hdr->bufrHeaderCentre = (long)grib_decode_unsigned_long(message, &pos_bufrHeaderCentre, nbits_bufrHeaderCentre);
hdr->updateSequenceNumber = (long)grib_decode_unsigned_long(message, &pos_updateSequenceNumber, nbits_updateSequenceNumber);
hdr->section1Flags = (long)grib_decode_unsigned_long(message, &pos_section1Flags, nbits_section1Flags);
section1Flags = (long)grib_decode_unsigned_long(message, &pos_section1Flags, nbits_section1Flags);
hdr->dataCategory = (long)grib_decode_unsigned_long(message, &pos_dataCategory, nbits_dataCategory);
hdr->dataSubCategory = (long)grib_decode_unsigned_long(message, &pos_dataSubCategory, nbits_dataSubCategory);
hdr->masterTablesVersionNumber = (long)grib_decode_unsigned_long(
@ -318,21 +356,21 @@ static int bufr_decode_edition3(const void* message, codes_bufr_header* hdr)
hdr->typicalMinute = (long)grib_decode_unsigned_long(message, &pos_typicalMinute, nbits_typicalMinute);
offset_section2 = BUFR_SECTION0_LEN + section1Length; /*bytes*/
hdr->section2Length = 0;
hdr->localSectionPresent = (hdr->section1Flags != 0);
section2Length = 0;
hdr->localSectionPresent = (section1Flags != 0);
if (hdr->localSectionPresent) {
long pos_section2Length;
const long nbits_section2Length = 3*8;
pos_section2Length = offset_section2*8;
hdr->section2Length = grib_decode_unsigned_long(message, &pos_section2Length, nbits_section2Length);
section2Length = grib_decode_unsigned_long(message, &pos_section2Length, nbits_section2Length);
if (hdr->bufrHeaderCentre == 98) {
err = bufr_decode_rdb_keys(message, offset_section2, hdr);
}
}
offset_section3 = BUFR_SECTION0_LEN + section1Length + hdr->section2Length; /*bytes*/
offset_section3 = BUFR_SECTION0_LEN + section1Length + section2Length; /*bytes*/
nbits_numberOfSubsets = 2*8;
pos_numberOfSubsets = (offset_section3+4)*8;
hdr->numberOfSubsets = grib_decode_unsigned_long(message, &pos_numberOfSubsets, nbits_numberOfSubsets);
@ -342,7 +380,7 @@ static int bufr_decode_edition3(const void* message, codes_bufr_header* hdr)
hdr->observedData = (section3Flags & 1<<7) ? 1 : 0;
hdr->compressedData = (section3Flags & 1<<6) ? 1 : 0;
if (hdr->localSectionPresent && hdr->bufrHeaderCentre == 98 && hdr->section2Length == 52) {
if (hdr->localSectionPresent && hdr->bufrHeaderCentre == 98 && section2Length == 52) {
err = bufr_decode_extra_rdb_keys(message, offset_section2, hdr);
}
@ -372,6 +410,7 @@ static int bufr_decode_edition4(const void* message, codes_bufr_header* hdr)
long nbits_updateSequenceNumber = 1*8;
long pos_updateSequenceNumber = 16*8;
long section1Flags = 0;
long nbits_section1Flags = 1*8;
long pos_section1Flags = 17*8;
@ -408,6 +447,7 @@ static int bufr_decode_edition4(const void* message, codes_bufr_header* hdr)
long nbits_typicalSecond = 1*8;
long pos_typicalSecond = 29*8;
long section2Length = 0;
long offset_section2 = 0;
long offset_section3 = 0;
long nbits_numberOfSubsets = 2*8;
@ -423,7 +463,7 @@ static int bufr_decode_edition4(const void* message, codes_bufr_header* hdr)
hdr->bufrHeaderCentre = (long)grib_decode_unsigned_long(message, &pos_bufrHeaderCentre, nbits_bufrHeaderCentre);
hdr->bufrHeaderSubCentre = (long)grib_decode_unsigned_long(message, &pos_bufrHeaderSubCentre, nbits_bufrHeaderSubCentre);
hdr->updateSequenceNumber = (long)grib_decode_unsigned_long(message, &pos_updateSequenceNumber, nbits_updateSequenceNumber);
hdr->section1Flags = (long)grib_decode_unsigned_long(message, &pos_section1Flags, nbits_section1Flags);
section1Flags = (long)grib_decode_unsigned_long(message, &pos_section1Flags, nbits_section1Flags);
hdr->dataCategory = (long)grib_decode_unsigned_long(message, &pos_dataCategory, nbits_dataCategory);
hdr->internationalDataSubCategory = (long)grib_decode_unsigned_long(message, &pos_internationalDataSubCategory, nbits_internationalDataSubCategory);
hdr->dataSubCategory = (long)grib_decode_unsigned_long(message, &pos_dataSubCategory, nbits_dataSubCategory);
@ -437,21 +477,21 @@ static int bufr_decode_edition4(const void* message, codes_bufr_header* hdr)
hdr->typicalSecond = (long)grib_decode_unsigned_long(message, &pos_typicalSecond, nbits_typicalSecond);
offset_section2 = BUFR_SECTION0_LEN + section1Length; /*bytes*/
hdr->section2Length = 0;
hdr->localSectionPresent = (hdr->section1Flags != 0);
section2Length = 0;
hdr->localSectionPresent = (section1Flags != 0);
if (hdr->localSectionPresent) {
long pos_section2Length;
const long nbits_section2Length = 3*8;
pos_section2Length = offset_section2*8;
hdr->section2Length = grib_decode_unsigned_long(message, &pos_section2Length, nbits_section2Length);
section2Length = grib_decode_unsigned_long(message, &pos_section2Length, nbits_section2Length);
if (hdr->bufrHeaderCentre == 98) {
err = bufr_decode_rdb_keys(message, offset_section2, hdr);
}
}
offset_section3 = BUFR_SECTION0_LEN + section1Length + hdr->section2Length; /*bytes*/
offset_section3 = BUFR_SECTION0_LEN + section1Length + section2Length; /*bytes*/
nbits_numberOfSubsets = 2*8;
pos_numberOfSubsets = (offset_section3+4)*8;
hdr->numberOfSubsets = grib_decode_unsigned_long(message, &pos_numberOfSubsets, nbits_numberOfSubsets);
@ -461,7 +501,7 @@ static int bufr_decode_edition4(const void* message, codes_bufr_header* hdr)
hdr->observedData = (section3Flags & 1<<7) ? 1 : 0;
hdr->compressedData = (section3Flags & 1<<6) ? 1 : 0;
if (hdr->localSectionPresent && hdr->bufrHeaderCentre == 98 && hdr->section2Length == 52) {
if (hdr->localSectionPresent && hdr->bufrHeaderCentre == 98 && section2Length == 52) {
err = bufr_decode_extra_rdb_keys(message, offset_section2, hdr);
}

View File

@ -1573,7 +1573,6 @@ typedef struct codes_bufr_header {
long bufrHeaderSubCentre;
long bufrHeaderCentre;
long updateSequenceNumber;
long section1Flags;
long dataCategory;
long dataSubCategory;
long masterTablesVersionNumber;
@ -1592,7 +1591,6 @@ typedef struct codes_bufr_header {
long localSectionPresent;
/* ECMWF local section keys */
unsigned long section2Length;
long rdbType;
long oldSubtype;
char ident[9];
@ -1613,9 +1611,18 @@ typedef struct codes_bufr_header {
long rectimeMinute;
long rectimeSecond;
long qualityControl;
long newSubtype;
long daLoop;
long isSatellite;
double localLongitude1;
double localLatitude1;
double localLongitude2;
double localLatitude2;
double localLatitude;
double localLongitude;
long localNumberOfObservations;
long satelliteID;
long qualityControl;
long newSubtype;
long daLoop;
/* Section 3 keys */
unsigned long numberOfSubsets;

View File

@ -13,16 +13,21 @@
static const char* not_found = "not_found";
void print_rdb_key(int has_local, long value)
static void print_rdb_key(int local, long value)
{
if (has_local)
printf("%ld ", value);
else
printf("%s ", not_found);
if (local) printf("%ld ", value);
else printf("%s ", not_found);
}
void print_rdb_ident(int has_local, const char* value)
static void print_rdb_key_double(int local, double value)
{
if (value == NULL || strlen(value) == 0)
if (local) printf("%g ", value);
else printf("%s ", not_found);
}
static void print_rdb_ident(int local, const char* value)
{
if (!local || value == NULL || strlen(value) == 0)
printf("%s ", not_found);
else
printf("%s ", value);
@ -47,8 +52,7 @@ int main(int argc, char* argv[])
for (i=0; i < num_messages; ++i) {
codes_bufr_header bh = headers[i];
/*
* Mimic the behaviour of bufr_get -f -p keys
* for testing
* Mimic the behaviour of bufr_get -f -p keys for testing
*/
const int has_ecmwf_local = (bh.localSectionPresent == 1 && bh.bufrHeaderCentre == 98);
@ -60,7 +64,6 @@ int main(int argc, char* argv[])
if (strstr(keys, "bufrHeaderSubCentre")) printf("%ld ", bh.bufrHeaderSubCentre);
if (strstr(keys, "bufrHeaderCentre")) printf("%ld ", bh.bufrHeaderCentre);
if (strstr(keys, "updateSequenceNumber")) printf("%ld ", bh.updateSequenceNumber);
if (strstr(keys, "section1Flags")) printf("%ld ", bh.section1Flags);
if (strstr(keys, "dataCategory")) printf("%ld ", bh.dataCategory);
if (strstr(keys, "dataSubCategory")) printf("%ld ", bh.dataSubCategory);
if (strstr(keys, "masterTablesVersionNumber")) printf("%ld ", bh.masterTablesVersionNumber);
@ -75,8 +78,6 @@ int main(int argc, char* argv[])
if (strstr(keys, "typicalSecond")) printf("%ld ", bh.typicalSecond);
if (strstr(keys, "localSectionPresent")) printf("%ld ", bh.localSectionPresent);
if (strstr(keys, "section2Length")) printf("%ld ", bh.section2Length);
if (strstr(keys, "rdbType")) print_rdb_key(has_ecmwf_local, bh.rdbType);
if (strstr(keys, "oldSubtype")) print_rdb_key(has_ecmwf_local, bh.oldSubtype);
if (strstr(keys, "localYear")) print_rdb_key(has_ecmwf_local, bh.localYear);
@ -97,9 +98,16 @@ int main(int argc, char* argv[])
if (strstr(keys, "newSubtype")) print_rdb_key(has_ecmwf_local, bh.newSubtype);
if (strstr(keys, "daLoop")) print_rdb_key(has_ecmwf_local, bh.daLoop);
if (strstr(keys, "numberOfSubsets")) printf("%ld ", bh.numberOfSubsets);
if (strstr(keys, "observedData")) printf("%ld ", bh.observedData);
if (strstr(keys, "compressedData")) printf("%ld ", bh.compressedData);
if (strstr(keys, "localLongitude1")) print_rdb_key_double(has_ecmwf_local, bh.localLongitude1);
if (strstr(keys, "localLatitude1")) print_rdb_key_double(has_ecmwf_local, bh.localLatitude1);
if (strstr(keys, "localLongitude2")) print_rdb_key_double(has_ecmwf_local, bh.localLongitude2);
if (strstr(keys, "localLatitude2")) print_rdb_key_double(has_ecmwf_local, bh.localLatitude2);
if (strstr(keys, "localNumberOfObservations")) printf("%ld ", bh.localNumberOfObservations);
if (strstr(keys, "satelliteID")) printf("%ld ", bh.satelliteID);
if (strstr(keys, "numberOfSubsets")) printf("%ld ", bh.numberOfSubsets);
if (strstr(keys, "observedData")) printf("%ld ", bh.observedData);
if (strstr(keys, "compressedData")) printf("%ld ", bh.compressedData);
if (strstr(keys, "ident")) print_rdb_ident(has_ecmwf_local, bh.ident);
printf("\n");

View File

@ -27,5 +27,116 @@ for bf in ${bufr_files}; do
diff -w $temp1 $temp2
done
# BUFRs with localLatitude1, localLongitude1, localLongitude2 etc
bufr_files="
aaen_55.bufr
aben_55.bufr
aeolus_wmo_26.bufr
ahws_139.bufr
airs_57.bufr
alws_139.bufr
amsa_55.bufr
amsb_55.bufr
amse_55.bufr
amsu_55.bufr
amv2_87.bufr
amv3_87.bufr
asbh_139.bufr
asbl_139.bufr
asca_139.bufr
asch_139.bufr
ascs_139.bufr
aseh_139.bufr
asel_139.bufr
ashs_139.bufr
atap_55.bufr
ateu_155.bufr
atms_201.bufr
atov_55.bufr
avhm_87.bufr
avhn_87.bufr
avhr_58.bufr
b003_56.bufr
b005_87.bufr
b005_89.bufr
b007_31.bufr
cmwi_87.bufr
cmwn_87.bufr
cori_156.bufr
crit_202.bufr
csrh_189.bufr
emsg_189.bufr
emsg_87.bufr
euwv_87.bufr
fy3a_154.bufr
fy3b_154.bufr
g2nd_208.bufr
g2to_206.bufr
go15_87.bufr
goee_87.bufr
goes_87.bufr
goga_89.bufr
gosat.bufr
grst_26.bufr
gsd1_208.bufr
gsd2_208.bufr
gsd3_208.bufr
gst4_26.bufr
hirb_55.bufr
hirs_55.bufr
ias1_240.bufr
iasi_241.bufr
ifco_208.bufr
ikco_217.bufr
imssnow.bufr
itrg_208.bufr
itwt_233.bufr
j2eo_216.bufr
j2nb_216.bufr
jaso_214.bufr
kond_209.bufr
maer_207.bufr
mhen_55.bufr
mhsa_55.bufr
mhsb_55.bufr
mhse_55.bufr
mloz_206.bufr
modi_87.bufr
modw_87.bufr
monw_87.bufr
nomi_206.bufr
nos1_208.bufr
nos2_208.bufr
nos3_208.bufr
nos4_208.bufr
nos5_208.bufr
nos6_208.bufr
nos7_208.bufr
nos8_208.bufr
pgps_110.bufr
rada_250.bufr
rado_250.bufr
s4kn_165.bufr
sb19_206.bufr
sbu8_206.bufr
smin_49.bufr
smis_49.bufr
smiu_49.bufr
smos_203.bufr
sn4k_165.bufr
ssbt_127.bufr
tmr7_129.bufr
tropical_cyclone.bufr
tros_31.bufr
"
KEYS='localLongitude1,localLatitude1,localLongitude2,localLatitude2,localNumberOfObservations,satelliteID'
for bf in ${bufr_files}; do
input=${data_dir}/bufr/$bf
$EXEC ${test_dir}/bufr_extract_headers $KEYS $input > $temp1
${tools_dir}/bufr_get -f -p $KEYS $input > $temp2
diff -w $temp1 $temp2
done
rm -f $temp1 $temp2