mirror of https://github.com/ecmwf/eccodes.git
ECC-1018: Encoding and decoding of DIAG pseudo-GRIB messages
This commit is contained in:
commit
ae2540dafb
|
@ -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" ;
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
Binary file not shown.
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue