ECC-1018: Encoding and decoding of DIAG pseudo-GRIB messages

This commit is contained in:
Shahram Najm 2019-12-16 13:58:53 +00:00
commit ae2540dafb
10 changed files with 267 additions and 7 deletions

View File

@ -64,10 +64,14 @@ if(kindOfProduct == `GRIB`){
template GRIB "grib[GRIBEditionNumber:l]/boot.def" ;
}
if(kindOfProduct == `BUDG`){
if(kindOfProduct == `BUDG` ){
template BUDG "budg/boot.def" ;
}
if(kindOfProduct == `DIAG`){
template DIAG "diag/boot.def" ;
}
if(kindOfProduct == `TIDE`){
template TIDE "tide/boot.def" ;
}

14
definitions/diag/boot.def Normal file
View File

@ -0,0 +1,14 @@
## Copyright 2005-2019 ECMWF.
position startOfHeaders;
ascii[4] identifier;
alias ls.identifier=identifier;
transient missingValue = 9999;
constant ieeeFloats = 0: edition_specific;
constant zero=0:hidden;
template section1 "diag/section.1.def";
template section4 "diag/section.4.def";
ascii[4] endMark;
position totalLength;

View File

@ -0,0 +1,79 @@
# Copyright 2005-2019 ECMWF.
section_length[3] section1Length ;
unsigned[1] gribTablesVersionNo ;
codetable[1] centre 'common/c-1.table' : string_type;
alias ls.centre=centre;
alias identificationOfOriginatingGeneratingCentre=centre;
unsigned[1] generatingProcessIdentifier ;
unsigned[1] gridDefinition ;
flags[1] flag 'grib1/1.table';
codetable[1] indicatorOfParameter 'grib1/2.[centre:l].[gribTablesVersionNo:l].table';
codetable[1] indicatorOfTypeOfLevel 'grib1/3.table';
codetable[2] heightPressureEtcOfLevels 'grib1/3.table';
alias ls.levelType=indicatorOfTypeOfLevel;
unsigned[1] yearOfCentury ;
unsigned[1] month ;
unsigned[1] day;
unsigned[1] hour ;
unsigned[1] minute ;
transient second = 0;
meta dataDate budgdate(yearOfCentury,month,day);
alias ls.date=dataDate;
meta dataTime time(hour,minute,second);
alias ls.time=dataTime;
meta julianDay julian_day(dataDate,hour,minute,second) : edition_specific;
# Indicator of unit of time range
codetable[1] indicatorOfUnitOfTimeRange 'grib1/4.table';
# P1 - Period of time (number of time units)
unsigned[1] periodOfTime ;
alias P1 = periodOfTime ;
# P2 - Period of time
unsigned[1] periodOfTimeIntervals ;
alias P2 = periodOfTimeIntervals ;
codetable[1] timeRangeIndicator 'grib1/5.table';
codetable[1] stepUnits 'grib2/tables/1/4.4.table' = 1 : transient,dump,no_copy;
concept stepType {
"instant" = {timeRangeIndicator=1;}
"instant" = {timeRangeIndicator=10;}
"instant" = {timeRangeIndicator=0;}
"avg" = {timeRangeIndicator=3;}
"accum" = {timeRangeIndicator=4;}
"max" = {timeRangeIndicator=2;}
"min" = {timeRangeIndicator=2;}
"diff" = {timeRangeIndicator=5;}
"rms" = {timeRangeIndicator=2;}
"sd" = {timeRangeIndicator=2;}
"cov" = {timeRangeIndicator=2;}
"ratio" = {timeRangeIndicator=2;}
}
meta ls.stepRange g1step_range(P1,P2,timeRangeIndicator,indicatorOfUnitOfTimeRange,stepUnits,stepType) : dump;
meta startStep long_vector(stepRange,0) : dump;
meta endStep long_vector(stepRange,1) : dump;
# Set stepUnits to 1 to get step range in hours
meta stepRangeInHours g1step_range(P1,P2,timeRangeIndicator,indicatorOfUnitOfTimeRange,one,stepType);
meta startStepInHours long_vector(stepRangeInHours,0) : dump;
meta endStepInHours long_vector(stepRangeInHours,1) : dump;
constant paramId = 0;
alias parameter = paramId;
alias ls.parameter=parameter;
section_padding section1Padding : read_only;

View File

@ -0,0 +1,41 @@
# Copyright 2005-2019 ECMWF.
section_length[3] section4Length ;
unsigned[1] reserved1=0 : hidden;
flags[1] missingDataFlag 'grib1/1.table';
unsigned[1] numberOfBytesPerInteger=4;
unsigned[2] reserved=0 : hidden ;
unsigned[3] numberOfCharacters : dump;
alias numberOfChars=numberOfCharacters ;
unsigned[3] numberOfFloats : dump;
unsigned[3] numberOfIntegers=0 : dump;
alias numberOfInts=numberOfIntegers ;
unsigned[3] numberOfLogicals ;
unsigned[3] numberOfReservedBytes ;
unsigned[4] reserved=0 : hidden;
unsigned[4] reserved=0 : hidden;
unsigned[1] reserved=0 : hidden;
ibmfloat floatValues[numberOfFloats] : dump;
alias floatVal=floatValues;
if (numberOfIntegers) {
signed[4] integerValues[numberOfIntegers] : dump;
}
# Have to use integers to represent single char strings
if (numberOfCharacters) {
unsigned[1] charValues[numberOfCharacters] : dump, string_type;
}
#charList list(numberOfCharacters) {
# ascii[1] charValues : dump;
#}
# Final padding
section_padding padding;

BIN
samples/diag.tmpl Normal file

Binary file not shown.

View File

@ -487,9 +487,23 @@ static int pack_double(grib_accessor* a, const double *v, size_t *len)
return GRIB_NOT_IMPLEMENTED;
}
static int pack_string_array(grib_accessor*a , const char** v, size_t *len)
static int pack_string_array(grib_accessor*a , const char** v, size_t *len)
{
return GRIB_NOT_IMPLEMENTED;
long i;
int err = 0;
size_t length = 0;
grib_accessor* as = 0;
as = a;
i = (long)*len - 1;
while(as && i >= 0) {
length = strlen(v[i]);
err = grib_pack_string(as, v[i], &length);
if (err) return err;
--i;
as = as->same;
}
return GRIB_SUCCESS;
}
static int pack_string(grib_accessor*a , const char* v, size_t *len){
@ -508,7 +522,7 @@ static int pack_string(grib_accessor*a , const char* v, size_t *len){
}
grib_context_log(a->context,GRIB_LOG_ERROR,
" Should not grib_pack %s as string", a->name);
" Should not grib_pack %s as string", a->name);
return GRIB_NOT_IMPLEMENTED;
}

View File

@ -404,6 +404,7 @@ static void dump_values(grib_dumper* d,grib_accessor* a)
double* buf = NULL;
size_t size=0;
long count=0;
int is_char = 0;
if( a->length == 0 &&
(d->option_flags & GRIB_DUMP_FLAG_CODED) != 0)
@ -420,6 +421,11 @@ static void dump_values(grib_dumper* d,grib_accessor* a)
set_begin_end(d,a);
/* For the DIAG pseudo GRIBs. Key charValues uses 1-byte integers to represent a character */
if ( a->flags & GRIB_ACCESSOR_FLAG_STRING_TYPE ) {
is_char = 1;
}
/*for(i = 0; i < d->depth ; i++) fprintf(self->dumper.out," ");*/
print_offset(self->dumper.out,self->begin,self->theEnd);
if ((d->option_flags & GRIB_DUMP_FLAG_TYPE) != 0)
@ -453,7 +459,6 @@ static void dump_values(grib_dumper* d,grib_accessor* a)
size = 100;
}
k = 0;
while(k < size)
{
@ -462,14 +467,16 @@ static void dump_values(grib_dumper* d,grib_accessor* a)
/*for(i = 0; i < d->depth + 3 ; i++) fprintf(self->dumper.out," ");*/
for(j = 0; j < 8 && k < size; j++, k++)
{
fprintf(self->dumper.out,"%.10e",buf[k]);
if (is_char) fprintf(self->dumper.out,"'%c'",(char)buf[k]);
else fprintf(self->dumper.out,"%.10e",buf[k]);
if(k != size-1)
fprintf(self->dumper.out,", ");
}
fprintf(self->dumper.out,"\n");
#else
fprintf(self->dumper.out,"%d %g\n",k,buf[k]);
if(is_char) fprintf(self->dumper.out,"%d '%c'\n",k,(char)buf[k]);
else fprintf(self->dumper.out,"%d %g\n",k,buf[k]);
#endif

View File

@ -66,6 +66,7 @@ list( APPEND tests_no_data_reqd
bufr_rdbSubTypes
grib_efas
grib_sh_imag
diag
)
# These tests do require data downloads
list( APPEND tests_data_reqd

80
tests/diag.sh Executable file
View File

@ -0,0 +1,80 @@
#!/bin/sh
# Copyright 2005-2019 ECMWF.
#
# This software is licensed under the terms of the Apache Licence Version 2.0
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
#
# In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
# virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
#
# Tests for Pseudo-GRIB format "DIAG"
. ./include.sh
label="pseudo-diag-test"
tempOut=temp.${label}.out
tempTxt=temp.${label}.txt
tempRef=temp.${label}.ref
REDIRECT=/dev/null
sample=$ECCODES_SAMPLES_PATH/diag.tmpl
# Basic grib commands should not fail
# ------------------------------------
${tools_dir}/grib_ls $sample > $REDIRECT
${tools_dir}/grib_dump $sample > $REDIRECT
# Check setting keys
# -------------------
echo 'set numberOfIntegers=3; set integerValues={55, 44, 66}; write;' | ${tools_dir}/grib_filter -o $tempOut - $sample
${tools_dir}/grib_dump -p numberOfFloats,numberOfIntegers,floatValues,integerValues $tempOut | sed 1d > $tempTxt
cat > $tempRef <<EOF
numberOfFloats = 2;
numberOfIntegers = 3;
floatValues(2) = {
3.32, 1.21
}
integerValues(3) = {
55, 44, 66
}
EOF
diff $tempRef $tempTxt
echo 'set numberOfFloats=3; set floatValues={8.8, 9.9, 10.10}; write;' | ${tools_dir}/grib_filter -o $tempOut - $sample
${tools_dir}/grib_dump -p numberOfFloats,numberOfIntegers,floatValues,integerValues $tempOut | sed 1d > $tempTxt
cat > $tempRef <<EOF
numberOfFloats = 3;
numberOfIntegers = 1;
floatValues(3) = {
8.8, 9.9, 10.1
}
integerValues = 66;
EOF
diff $tempRef $tempTxt
echo 'set numberOfIntegers=4; set integerValues={33, 55, -44, 66}; set numberOfFloats=3; set floatValues={-8.8, 9.9, 10.10}; write;' |\
${tools_dir}/grib_filter -o $tempOut - $sample
${tools_dir}/grib_dump -p numberOfFloats,numberOfIntegers,floatValues,integerValues $tempOut | sed 1d > $tempTxt
cat > $tempRef <<EOF
numberOfFloats = 3;
numberOfIntegers = 4;
floatValues(3) = {
-8.8, 9.9, 10.1
}
integerValues(4) = {
33, 55, -44, 66
}
EOF
diff $tempRef $tempTxt
# TODO encoding of characters not fully working. We are using one-byte integers instead
#echo 'set numberOfCharacters=4; set charValues={"J","u","m","p"}; write;'| ${tools_dir}/grib_filter -o $tempOut - $sample
#res=`${tools_dir}/grib_dump $tempOut | grep charValues | tr -d '\n' | tr -d ' '`
#[ "$res" = "charValues=J;charValues=u;charValues=m;charValues=p;" ]
# Clean up
rm -f $tempOut $tempRef

View File

@ -65,6 +65,7 @@ diff local.log local.good.log
rm -f local.log loc.grib1 loc.grib2 loc1.grib1 loc1.grib2 eps.grib1 eps.grib2
# Delete Local Definition
# -----------------------
sample_g1=$ECCODES_SAMPLES_PATH/reduced_gg_pl_640_grib1.tmpl
@ -79,6 +80,7 @@ ${tools_dir}/grib_set -s deleteLocalDefinition=1 $sample_g2 $temp
grib_check_key_equals $temp "localUsePresent,section2Used" "0 0"
rm -f $temp
# Empty local section for GRIB2
# ------------------------------
sample_g2=$ECCODES_SAMPLES_PATH/reduced_gg_pl_640_grib2.tmpl
@ -92,6 +94,7 @@ ${tools_dir}/grib_set -s addEmptySection2=1 $sample_g2 $temp
grib_check_key_equals $temp section2Length 5
rm -f $temp
# Local Definition 5
# -----------------------
sample_g1=$ECCODES_SAMPLES_PATH/GRIB1.tmpl
@ -106,13 +109,30 @@ grib_check_key_equals $temp.3 edition,productDefinitionTemplateNumber "2 5"
grib_check_key_equals $temp.3 forecastProbabilityNumber,totalNumberOfForecastProbabilities "2 25"
grib_check_key_equals $temp.3 probabilityType,scaledValueOfLowerLimit,scaledValueOfUpperLimit "2 54 56"
# Local Definition 42 for GRIB2 (LC-WFV)
# ---------------------------------------
${tools_dir}/grib_set -s setLocalDefinition=1,localDefinitionNumber=42,lcwfvSuiteName=9 $sample_g2 $temp
grib_check_key_equals $temp 'mars.origin:s' 'lops'
# Extra key in Local Definition 16 for GRIB1. ECC-679
${tools_dir}/grib_set -s setLocalDefinition=1,localDefinitionNumber=16,numberOfForecastsInEnsemble=51 $sample_g1 $temp
grib_check_key_equals $temp 'totalNumber' '51'
# Local Definition 18 (list of ascii keys)
# ----------------------------------------
${tools_dir}/grib_filter -o $temp - $sample_g1 << EOF
set setLocalDefinition=1;
set localDefinitionNumber=18;
set consensusCount=3;
set ccccIdentifiers={"kwbc","ecmf","sabm"};
write;
EOF
result=`echo 'print "[ccccIdentifiers]";' | ${tools_dir}/grib_filter - $temp`
[ "$result" = "kwbc ecmf sabm" ]
rm -f $temp $temp.1 $temp.2 $temp.3