mirror of https://github.com/ecmwf/eccodes.git
Merge branch 'develop' into feature/Template4refactoring
This commit is contained in:
commit
bc33269b52
|
@ -14041,7 +14041,6 @@ dist_definitionsgrib2_DATA = \
|
|||
grib2/template.7.6.def\
|
||||
grib2/template.7.61.def\
|
||||
grib2/template.7.second_order.def\
|
||||
grib2/template.second_order.def\
|
||||
grib2/tiggeLocalVersion.table\
|
||||
grib2/tigge_name.def\
|
||||
grib2/tigge_parameter.def\
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
# parameterNumber
|
||||
# # The following are optional keys
|
||||
# typeOfFirstFixedSurface
|
||||
# typeOfSecondFixedSurface
|
||||
# scaledValueOfFirstFixedSurface
|
||||
# scaleFactorOfFirstFixedSurface
|
||||
# scaledValueOfSecondFixedSurface
|
||||
# scaledValueOfFirstFixedSurface
|
||||
# typeOfSecondFixedSurface
|
||||
# scaleFactorOfSecondFixedSurface
|
||||
# scaledValueOfSecondFixedSurface
|
||||
# typeOfStatisticalProcessing
|
||||
#
|
||||
# It outputs the def files:
|
||||
|
@ -57,6 +57,7 @@ write_or_append(\*OUT_CFVARNAME, "$CFVARNAME_FILENAME");
|
|||
my $first = 1;
|
||||
while (<>) {
|
||||
chomp;
|
||||
s/\r//g; # Remove DOS carriage returns
|
||||
if ($first == 1) {
|
||||
check_first_row_column_names($_);
|
||||
$first = 0;
|
||||
|
@ -124,13 +125,12 @@ sub check_first_row_column_names {
|
|||
die "Error: 1st row column titles wrong: Column 7 should be 'parameterNumber'\n" if ($keys[6] ne "parameterNumber");
|
||||
|
||||
die "Error: 1st row column titles wrong: Column 8 should be 'typeOfFirstFixedSurface'\n" if ($keys[7] ne "typeOfFirstFixedSurface");
|
||||
die "Error: 1st row column titles wrong: Column 9 should be 'typeOfSecondFixedSurface'\n" if ($keys[8] ne "typeOfSecondFixedSurface");
|
||||
|
||||
die "Error: 1st row column titles wrong: Column 9 should be 'scaleFactorOfFirstFixedSurface'\n" if ($keys[8] ne "scaleFactorOfFirstFixedSurface");
|
||||
die "Error: 1st row column titles wrong: Column 10 should be 'scaledValueOfFirstFixedSurface'\n" if ($keys[9] ne "scaledValueOfFirstFixedSurface");
|
||||
die "Error: 1st row column titles wrong: Column 11 should be 'scaleFactorOfFirstFixedSurface'\n" if ($keys[10] ne "scaleFactorOfFirstFixedSurface");
|
||||
|
||||
die "Error: 1st row column titles wrong: Column 12 should be 'scaledValueOfSecondFixedSurface'\n" if ($keys[11] ne "scaledValueOfSecondFixedSurface");
|
||||
die "Error: 1st row column titles wrong: Column 13 should be 'scaleFactorOfSecondFixedSurface'\n" if ($keys[12] ne "scaleFactorOfSecondFixedSurface");
|
||||
die "Error: 1st row column titles wrong: Column 11 should be 'typeOfSecondFixedSurface'\n" if ($keys[10] ne "typeOfSecondFixedSurface");
|
||||
die "Error: 1st row column titles wrong: Column 12 should be 'scaleFactorOfSecondFixedSurface'\n" if ($keys[11] ne "scaleFactorOfSecondFixedSurface");
|
||||
die "Error: 1st row column titles wrong: Column 13 should be 'scaledValueOfSecondFixedSurface'\n" if ($keys[12] ne "scaledValueOfSecondFixedSurface");
|
||||
die "Error: 1st row column titles wrong: Column 14 should be 'typeOfStatisticalProcessing'\n" if ($keys[13] ne "typeOfStatisticalProcessing");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,37 +1,4 @@
|
|||
# ECMWF concept type of level
|
||||
'surface' = {indicatorOfTypeOfLevel=1;}
|
||||
'cloudBase' = {indicatorOfTypeOfLevel=2;}
|
||||
'cloudTop' = {indicatorOfTypeOfLevel=3;}
|
||||
'isothermZero' = {indicatorOfTypeOfLevel=4;}
|
||||
'adiabaticCondensation' = {indicatorOfTypeOfLevel=5;}
|
||||
'maxWind' = {indicatorOfTypeOfLevel=6;}
|
||||
'tropopause' = {indicatorOfTypeOfLevel=7;}
|
||||
'nominalTop' = {indicatorOfTypeOfLevel=8;}
|
||||
'seaBottom' = {indicatorOfTypeOfLevel=9;}
|
||||
'isobaricInhPa' = {indicatorOfTypeOfLevel=100;}
|
||||
'isobaricInPa' = {indicatorOfTypeOfLevel=210;}
|
||||
'isobaricLayer' = {indicatorOfTypeOfLevel=101;}
|
||||
'meanSea' = {indicatorOfTypeOfLevel=102;}
|
||||
'isobaricLayerHighPrecision' = {indicatorOfTypeOfLevel=121;}
|
||||
'isobaricLayerMixedPrecision' = {indicatorOfTypeOfLevel=141;}
|
||||
'heightAboveSea' = {indicatorOfTypeOfLevel=103;}
|
||||
'heightAboveSeaLayer' = {indicatorOfTypeOfLevel=104;}
|
||||
'heightAboveGroundHighPrecision' = {indicatorOfTypeOfLevel=125;}
|
||||
'heightAboveGround' = {indicatorOfTypeOfLevel=105;}
|
||||
'heightAboveGroundLayer' = {indicatorOfTypeOfLevel=106;}
|
||||
'sigma' = {indicatorOfTypeOfLevel=107;}
|
||||
'sigmaLayer' = {indicatorOfTypeOfLevel=108;}
|
||||
'sigmaLayerHighPrecision' = {indicatorOfTypeOfLevel=128;}
|
||||
'hybrid' = {indicatorOfTypeOfLevel=109;}
|
||||
'hybridLayer' = {indicatorOfTypeOfLevel=110;}
|
||||
'depthBelowLand' = {indicatorOfTypeOfLevel=111;}
|
||||
'depthBelowLandLayer' = {indicatorOfTypeOfLevel=112;}
|
||||
'theta' = {indicatorOfTypeOfLevel=113;}
|
||||
'thetaLayer' = {indicatorOfTypeOfLevel=114;}
|
||||
'pressureFromGround' = {indicatorOfTypeOfLevel=115;}
|
||||
'pressureFromGroundLayer' = {indicatorOfTypeOfLevel=116;}
|
||||
'potentialVorticity' = {indicatorOfTypeOfLevel=117;}
|
||||
'depthBelowSea' = {indicatorOfTypeOfLevel=160;}
|
||||
'entireAtmosphere' = {indicatorOfTypeOfLevel=200;level=0;}
|
||||
'entireOcean' = {indicatorOfTypeOfLevel=201;level=0;}
|
||||
'oceanWave' = {indicatorOfTypeOfLevel=211;}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
# Concept typeOfLevel for kwbc
|
||||
'atmosphereSingleLayer' = {typeOfFirstFixedSurface=200;}
|
||||
'oceanSingleLayer' = {typeOfFirstFixedSurface=201;}
|
||||
'highestTroposphericFreezing' = {typeOfFirstFixedSurface=204;}
|
||||
'gridScaleCloudBottom' = {typeOfFirstFixedSurface=206;}
|
||||
'gridScaleCloudTop' = {typeOfFirstFixedSurface=207;}
|
||||
'boundaryLayerCloudBottom' = {typeOfFirstFixedSurface=209;}
|
||||
'boundaryLayerCloudTop' = {typeOfFirstFixedSurface=210;}
|
||||
'boundaryLayerCloudLayer' = {typeOfFirstFixedSurface=211;}
|
||||
'lowCloudBottom' = {typeOfFirstFixedSurface=212;}
|
||||
'lowCloudTop' = {typeOfFirstFixedSurface=213;}
|
||||
'lowCloudLayer' = {typeOfFirstFixedSurface=214;}
|
||||
'cloudCeiling' = {typeOfFirstFixedSurface=215;}
|
||||
'planetaryBoundaryLayer' = {typeOfFirstFixedSurface=220;}
|
||||
'layerBetween2Hybrids' = {typeOfFirstFixedSurface=221;}
|
||||
'middleCloudBottom' = {typeOfFirstFixedSurface=222;}
|
||||
'middleCloudTop' = {typeOfFirstFixedSurface=223;}
|
||||
'middleCloudLayer' = {typeOfFirstFixedSurface=224;}
|
||||
'highCloudBottom' = {typeOfFirstFixedSurface=232;}
|
||||
'highCloudTop' = {typeOfFirstFixedSurface=233;}
|
||||
'highCloudLayer' = {typeOfFirstFixedSurface=234;}
|
||||
'oceanIsotherm' = {typeOfFirstFixedSurface=235;}
|
||||
'oceanMixedLayer' = {typeOfFirstFixedSurface=240;}
|
||||
'orderedSequenceData' = {typeOfFirstFixedSurface=241;}
|
||||
'convectiveCloudBottom' = {typeOfFirstFixedSurface=242;}
|
||||
'convectiveCloudTop' = {typeOfFirstFixedSurface=243;}
|
||||
'convectiveCloudLayer' = {typeOfFirstFixedSurface=244;}
|
||||
'lowestLevelWetBulb0' = {typeOfFirstFixedSurface=245;}
|
||||
'equilibrium' = {typeOfFirstFixedSurface=247;}
|
||||
'shallowConvectiveCloudBottom' = {typeOfFirstFixedSurface=248;}
|
||||
'shallowConvectiveCloudTop' = {typeOfFirstFixedSurface=249;}
|
||||
'deepConvectiveCloudBottom' = {typeOfFirstFixedSurface=251;}
|
||||
'deepConvectiveCloudTop' = {typeOfFirstFixedSurface=252;}
|
|
@ -71,19 +71,42 @@
|
|||
# 192-254 Reserved for local use
|
||||
# See ECC-469
|
||||
200 200 Entire atmosphere (considered as a single layer)
|
||||
201 201 Entire ocean (considered as a single layer)
|
||||
204 204 Highest tropospheric freezing level
|
||||
206 206 Grid scale cloud bottom level
|
||||
207 207 Grid scale cloud top level
|
||||
209 209 Boundary layer cloud bottom level
|
||||
210 210 Boundary layer cloud top level
|
||||
211 211 Boundary layer cloud layer
|
||||
212 212 Low cloud bottom level
|
||||
213 213 Low cloud top level
|
||||
214 214 Low cloud layer
|
||||
215 215 Cloud ceiling
|
||||
220 220 Planetary boundary layer
|
||||
221 221 Layer between two hybrid levels
|
||||
222 222 Middle cloud bottom level
|
||||
223 223 Middle cloud top level
|
||||
224 224 Middle cloud layer
|
||||
232 232 High cloud bottom level
|
||||
233 233 High cloud top level
|
||||
234 234 High cloud layer
|
||||
235 235 Ocean isotherm level (1/10 deg C)
|
||||
236 236 Layer between two depths below ocean surface
|
||||
237 237 Bottom of ocean mixed layer
|
||||
238 238 Bottom of ocean isothermal layer
|
||||
239 239 Layer ocean surface and 26C ocean isothermal level
|
||||
240 240 Ocean mixed layer
|
||||
241 241 Ordered sequence of data
|
||||
242 242 Convective cloud bottom level
|
||||
243 243 Convective cloud top level
|
||||
244 244 Convective cloud layer
|
||||
245 245 Lowest level of the wet bulb zero
|
||||
246 246 Maximum equivalent potential temperature level
|
||||
247 247 Equilibrium level
|
||||
248 248 Shallow convective cloud bottom level
|
||||
249 249 Shallow convective cloud top level
|
||||
251 251 Deep convective cloud bottom level
|
||||
252 252 Deep convective cloud top level
|
||||
253 253 Lowest bottom level of supercooled liquid water layer
|
||||
254 254 Highest top level of supercooled liquid water layer
|
||||
255 255 Missing
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
# (C) Copyright 2005- ECMWF.
|
||||
|
||||
# TEMPLATE 7.4, Grid point data - simple packing
|
||||
# Octets 6-nn : Binary data values - binary string, with each
|
||||
# (scaled)
|
||||
# ???? data_values__binary_string_with_each
|
||||
# TEMPLATE 7.4, Grid point data - IEEE floating point data
|
||||
|
||||
meta codedValues data_raw_packing(
|
||||
section7Length,
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#TODO
|
|
@ -12,7 +12,6 @@
|
|||
* C Implementation: grib_iterator
|
||||
*
|
||||
* Description: how to use an iterator on lat/lon/values for GRIB messages
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -33,6 +32,7 @@ int main(int argc, char** argv)
|
|||
double lat, lon, value;
|
||||
double missingValue = 1e+20; /* A value out of range */
|
||||
int n = 0;
|
||||
long bitmapPresent = 0;
|
||||
char* filename = NULL;
|
||||
|
||||
/* Message handle. Required in all the ecCodes calls acting on a message.*/
|
||||
|
@ -55,9 +55,14 @@ int main(int argc, char** argv)
|
|||
/* Check of errors after reading a message. */
|
||||
if (err != CODES_SUCCESS) CODES_CHECK(err, 0);
|
||||
|
||||
/* Check if a bitmap applies */
|
||||
CODES_CHECK(codes_get_long(h, "bitmapPresent", &bitmapPresent), 0);
|
||||
|
||||
if (bitmapPresent) {
|
||||
/* Set the double representing the missing value in the field. */
|
||||
/* Choose a missingValue that does not correspond to any real value in the data array */
|
||||
CODES_CHECK(codes_set_double(h, "missingValue", missingValue), 0);
|
||||
}
|
||||
|
||||
/* A new iterator on lat/lon/values is created from the message handle h. */
|
||||
iter = codes_grib_iterator_new(h, 0, &err);
|
||||
|
@ -69,7 +74,7 @@ int main(int argc, char** argv)
|
|||
/* You can now print lat and lon, */
|
||||
printf("- %d - lat=%f lon=%f value=", n, lat, lon);
|
||||
/* decide what to print if a missing value is found. */
|
||||
if (value == missingValue) printf("missing\n");
|
||||
if (bitmapPresent && value == missingValue) printf("missing\n");
|
||||
/* and print the value if is not missing. */
|
||||
else
|
||||
printf("%f\n", value);
|
||||
|
|
|
@ -8,8 +8,15 @@
|
|||
# virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
|
||||
|
||||
. ./include.sh
|
||||
temp=temp.c_grib_iterator.txt
|
||||
|
||||
# These two do not have any missing data
|
||||
${examples_dir}/c_grib_iterator ${data_dir}/reduced_gaussian_model_level.grib1 > /dev/null
|
||||
|
||||
${examples_dir}/c_grib_iterator ${data_dir}/regular_gaussian_model_level.grib1 > /dev/null
|
||||
|
||||
# Has missing data
|
||||
${examples_dir}/c_grib_iterator ${data_dir}/reduced_latlon_surface.grib2 > $temp
|
||||
count_miss=`grep -c missing $temp`
|
||||
[ $count_miss = 98701 ]
|
||||
|
||||
rm -f $temp
|
||||
|
|
|
@ -37,7 +37,6 @@ character(len=32) :: units, confUnits
|
|||
! We need to instruct ecCodes to expand all the descriptors
|
||||
! i.e. unpack the data values
|
||||
call codes_set(ibufr, "unpack", 1);
|
||||
|
||||
! ----------------------------------------------------------------
|
||||
! We will read the value and all the attributes available for
|
||||
! the 2m temperature.
|
||||
|
|
|
@ -36,7 +36,6 @@ real(kind=8), dimension(:), allocatable :: values
|
|||
! We need to instruct ecCodes to expand all the descriptors
|
||||
! i.e. unpack the data values
|
||||
call codes_set(ibufr, "unpack", 1);
|
||||
|
||||
! Get the expanded data values
|
||||
call codes_get(ibufr, 'numericValues', values)
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@ character(len=9) :: typicalDate
|
|||
! We need to instruct ecCodes to expand all the descriptors
|
||||
! i.e. unpack the data values
|
||||
call codes_set(ibufr, "unpack", 1);
|
||||
|
||||
! Get as character
|
||||
call codes_get(ibufr, 'typicalDate', typicalDate)
|
||||
write (*, *) ' typicalDate:', typicalDate
|
||||
|
|
|
@ -38,7 +38,6 @@ integer :: kiter
|
|||
! We need to instruct ecCodes to expand all the descriptors
|
||||
! i.e. unpack the data values
|
||||
call codes_set(ibufr, "unpack", 1);
|
||||
|
||||
! Create BUFR keys iterator
|
||||
call codes_bufr_keys_iterator_new(ibufr, kiter, iret)
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
! below might not work directly for other types of messages than the one used in the
|
||||
! example. It is advised to use bufr_dump first to understand the structure of these messages.
|
||||
|
||||
|
||||
program bufr_read_scatterometer
|
||||
use eccodes
|
||||
implicit none
|
||||
|
@ -40,7 +39,6 @@ real(kind=8), dimension(:), allocatable :: year
|
|||
! We need to instruct ecCodes to expand all the descriptors
|
||||
! i.e. unpack the data values
|
||||
call codes_set(ibufr, "unpack", 1);
|
||||
|
||||
! The BUFR file contains a single message with 2016 subsets in a compressed form.
|
||||
! It means each subset has exactly the same structure: they store one location with
|
||||
! several beams and one backscatter value in each beam.
|
||||
|
@ -55,10 +53,8 @@ real(kind=8), dimension(:), allocatable :: year
|
|||
|
||||
! Get latitude (for all the subsets)
|
||||
call codes_get(ibufr, 'latitude', latVal);
|
||||
|
||||
! Get longitude (for all the subsets)
|
||||
call codes_get(ibufr, 'longitude', lonVal);
|
||||
|
||||
allocate (year(numObs))
|
||||
call codes_get(ibufr, 'year', year);
|
||||
do ii = 1, size(year)
|
||||
|
@ -68,7 +64,6 @@ real(kind=8), dimension(:), allocatable :: year
|
|||
! Get backScatter for beam two. We use an access by condition for this key.
|
||||
! (for all the subsets)
|
||||
call codes_get(ibufr, '/beamIdentifier=2/backscatter', bscatterVal);
|
||||
|
||||
! Check that all arrays are same size
|
||||
if (size(latVal) /= numObs .or. size(lonVal) /= numObs .or. size(bscatterVal) /= numObs) then
|
||||
print *, 'inconsistent array dimension'
|
||||
|
|
|
@ -54,7 +54,6 @@ program bufr_read_temp
|
|||
! we need to instruct ecCodes to expand all the descriptors
|
||||
! i.e. unpack the data values
|
||||
call codes_set(ibufr, "unpack", 1);
|
||||
|
||||
! In our BUFR message verticalSoundingSignificance is always followed by
|
||||
! geopotential, airTemperature, dewpointTemperature,
|
||||
! windDirection, windSpeed and pressure.
|
||||
|
|
|
@ -52,7 +52,6 @@ program bufr_read_tropical_cyclone
|
|||
|
||||
! We need to instruct ecCodes to unpack the data values
|
||||
call codes_set(ibufr, "unpack", 1);
|
||||
|
||||
call codes_get(ibufr, 'year', year);
|
||||
call codes_get(ibufr, 'month', month);
|
||||
call codes_get(ibufr, 'day', day);
|
||||
|
@ -234,8 +233,9 @@ program bufr_read_tropical_cyclone
|
|||
write (*, *) 'step latitude longitude pressure latitude longitude wind'
|
||||
do j = 1, size(period)
|
||||
if (latitude(i, j) /= CODES_MISSING_DOUBLE .OR. latitudeWind(i, j) /= CODES_MISSING_DOUBLE) then
|
||||
write(*,'( I4,2X,F8.2,4X,F8.2,3X,F9.1,2X,F8.2,4X,F8.2,2X,F8.2)') period(j),latitude(i,j),longitude(i,j),pressure(i,j),&
|
||||
&latitudeWind(i,j),longitudeWind(i,j),wind(i,j)
|
||||
write (*, '( I4,2X,F8.2,4X,F8.2,3X,F9.1,2X,F8.2,4X,F8.2,2X,F8.2)') &
|
||||
period(j), latitude(i, j), longitude(i, j), pressure(i, j), &
|
||||
latitudeWind(i, j), longitudeWind(i, j), wind(i, j)
|
||||
end if
|
||||
end do
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@ character(100) :: key
|
|||
! We need to instruct ecCodes to expand all the descriptors
|
||||
! i.e. unpack the data values
|
||||
call codes_set(ibufr, 'unpack', 1);
|
||||
|
||||
! Find out the number of subsets
|
||||
call codes_get(ibufr, 'numberOfSubsets', numberOfSubsets)
|
||||
write (*, *) ' numberOfSubsets:', numberOfSubsets
|
||||
|
|
|
@ -23,7 +23,6 @@ program copy
|
|||
character(len=1), dimension(:), allocatable :: message
|
||||
character(len=32) :: product_kind
|
||||
|
||||
|
||||
call codes_open_file(infile, '../../data/constant_field.grib1', 'r')
|
||||
call codes_open_file(outfile, 'out.copy.grib1', 'w')
|
||||
|
||||
|
|
|
@ -81,7 +81,6 @@ program get
|
|||
write (*, *) 'longitudeOfLastGridPointInDegrees=', &
|
||||
longitudeOfLastPointInDegrees
|
||||
|
||||
|
||||
! get the size of the values array
|
||||
call codes_get_size(igrib(i), 'values', numberOfValues)
|
||||
write (*, *) 'numberOfValues=', numberOfValues
|
||||
|
|
|
@ -57,7 +57,6 @@ program keys_iterator
|
|||
call codes_grib_new_from_file(ifile, igrib, iret)
|
||||
end do
|
||||
|
||||
|
||||
call codes_close_file(ifile)
|
||||
|
||||
end program keys_iterator
|
||||
|
|
|
@ -35,7 +35,6 @@ use eccodes
|
|||
call codes_check(iret, 'new_from_file', '')
|
||||
end if
|
||||
|
||||
|
||||
call codes_close_file(ifile)
|
||||
|
||||
end program
|
||||
|
|
|
@ -11,41 +11,43 @@
|
|||
/*
|
||||
* C Implementation: grib_iterator
|
||||
*
|
||||
* Description: how to use an iterator on lat/lon/values.
|
||||
* Description: how to use an iterator on lat/lon/values for GRIB messages
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "grib_api.h"
|
||||
|
||||
static void usage(const char* prog) {
|
||||
static void usage(const char* prog)
|
||||
{
|
||||
printf("Usage: %s grib_file\n", prog);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
FILE* in = NULL;
|
||||
int err = 0;
|
||||
double lat, lon, value;
|
||||
double missingValue = 1e+20; /* A value out of range */
|
||||
int n = 0;
|
||||
long bitmapPresent = 0;
|
||||
char* filename = NULL;
|
||||
|
||||
/* Message handle. Required in all the grib_api calls acting on a message.*/
|
||||
/* Message handle. Required in all the ecCodes calls acting on a message.*/
|
||||
grib_handle* h = NULL;
|
||||
/* Iterator on lat/lon/values.*/
|
||||
grib_iterator* iter = NULL;
|
||||
|
||||
if (argc != 2) usage(argv[0]);
|
||||
|
||||
filename=strdup(argv[1]);
|
||||
filename = argv[1];
|
||||
|
||||
in = fopen(filename, "rb");
|
||||
if (!in) {
|
||||
printf("ERROR: unable to open file %s\n",filename);
|
||||
fprintf(stderr, "Error: unable to open file %s\n", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -54,9 +56,14 @@ int main(int argc, char** argv) {
|
|||
/* Check of errors after reading a message. */
|
||||
if (err != GRIB_SUCCESS) GRIB_CHECK(err, 0);
|
||||
|
||||
/* Check if a bitmap applies */
|
||||
GRIB_CHECK(grib_get_long(h, "bitmapPresent", &bitmapPresent), 0);
|
||||
|
||||
if (bitmapPresent) {
|
||||
/* Set the double representing the missing value in the field. */
|
||||
/* Choose a missingValue that does not correspond to any real value in the data array */
|
||||
GRIB_CHECK(grib_set_double(h, "missingValue", missingValue), 0);
|
||||
}
|
||||
|
||||
/* A new iterator on lat/lon/values is created from the message handle h. */
|
||||
iter = grib_iterator_new(h, 0, &err);
|
||||
|
@ -68,9 +75,10 @@ int main(int argc, char** argv) {
|
|||
/* You can now print lat and lon, */
|
||||
printf("- %d - lat=%.6e lon=%.6e value=", n, lat, lon);
|
||||
/* decide what to print if a missing value is found. */
|
||||
if (value == missingValue ) printf("missing\n");
|
||||
if (bitmapPresent && value == missingValue) printf("missing\n");
|
||||
/* and print the value if is not missing. */
|
||||
else printf("%f\n",value);
|
||||
else
|
||||
printf("%f\n", value);
|
||||
n++;
|
||||
}
|
||||
|
||||
|
@ -81,7 +89,6 @@ int main(int argc, char** argv) {
|
|||
grib_handle_delete(h);
|
||||
}
|
||||
|
||||
|
||||
fclose(in);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -19,13 +19,16 @@ missingValue = 1e+20 # A value out of range
|
|||
|
||||
|
||||
def example(INPUT):
|
||||
f = open(INPUT, 'rb')
|
||||
f = open(INPUT, "rb")
|
||||
|
||||
while 1:
|
||||
gid = codes_grib_new_from_file(f)
|
||||
if gid is None:
|
||||
break
|
||||
|
||||
bitmapPresent = codes_get(gid, "bitmapPresent")
|
||||
|
||||
if bitmapPresent:
|
||||
# Set the value representing the missing value in the field.
|
||||
# Choose a missingValue that does not correspond to any real value in the data array
|
||||
codes_set(gid, "missingValue", missingValue)
|
||||
|
@ -42,7 +45,7 @@ def example(INPUT):
|
|||
|
||||
sys.stdout.write("- %d - lat=%.6e lon=%.6e value=" % (i, lat, lon))
|
||||
|
||||
if value == missingValue:
|
||||
if bitmapPresent and value == missingValue:
|
||||
print("missing")
|
||||
else:
|
||||
print("%.6f" % value)
|
||||
|
|
|
@ -24,7 +24,6 @@ module eccodes
|
|||
integer, parameter, public :: CODES_PRODUCT_GRIB = 1
|
||||
integer, parameter, public :: CODES_PRODUCT_BUFR = 2
|
||||
|
||||
|
||||
!> Create a new message in memory from an integer or character array containting the coded message.
|
||||
!>
|
||||
!> The message can be accessed through its ID and it will be available\n
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
! 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.
|
||||
|
||||
|
||||
!> Get the distinct values of the key in argument contained in the index. The key must belong to the index.
|
||||
!>
|
||||
!>
|
||||
|
@ -105,7 +104,6 @@
|
|||
codes_get_real8_array
|
||||
end interface codes_get
|
||||
|
||||
|
||||
!> Get the size of an array key.
|
||||
!>
|
||||
!> To get the size of a key representing an array.
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
! 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.
|
||||
|
||||
|
||||
!> Get the distinct values of the key in argument contained in the index. The key must belong to the index.
|
||||
!>
|
||||
!>
|
||||
|
|
|
@ -1096,7 +1096,6 @@ subroutine codes_bufr_new_from_file ( ifile, bufrid , status)
|
|||
call bufr_new_from_file(ifile, bufrid, status)
|
||||
end subroutine codes_bufr_new_from_file
|
||||
|
||||
|
||||
!> Create a new message in memory from a character array containting the coded message.
|
||||
!>
|
||||
!> The message can be accessed through its msgid and it will be available\n
|
||||
|
@ -1415,7 +1414,6 @@ subroutine codes_keys_iterator_rewind ( iterid, status )
|
|||
call grib_keys_iterator_rewind(iterid, status)
|
||||
end subroutine codes_keys_iterator_rewind
|
||||
|
||||
|
||||
! BUFR keys iterator
|
||||
! -----------------------
|
||||
!> Create a new iterator on the keys of a BUFR message.
|
||||
|
@ -1445,7 +1443,6 @@ subroutine codes_bufr_keys_iterator_new ( msgid, iterid, status )
|
|||
end if
|
||||
end subroutine codes_bufr_keys_iterator_new
|
||||
|
||||
|
||||
!> Advance to the next BUFR keys iterator value.
|
||||
!>
|
||||
!> @param iterid keys iterator id created with @ref codes_bufr_keys_iterator_new
|
||||
|
@ -1463,7 +1460,6 @@ subroutine codes_bufr_keys_iterator_next (iterid , status)
|
|||
end if
|
||||
end subroutine codes_bufr_keys_iterator_next
|
||||
|
||||
|
||||
!> Get the name of a key from a BUFR keys iterator.
|
||||
!>
|
||||
!> If the status parameter (optional) is not given the program will exit with an error message\n
|
||||
|
@ -1528,8 +1524,6 @@ end subroutine codes_bufr_keys_iterator_get_name
|
|||
end if
|
||||
end subroutine codes_bufr_keys_iterator_delete
|
||||
|
||||
|
||||
|
||||
!> Dump the content of a message.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -1545,7 +1539,6 @@ subroutine codes_dump ( msgid , status)
|
|||
call grib_dump(msgid, status)
|
||||
end subroutine codes_dump
|
||||
|
||||
|
||||
!> Get the API version
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -1564,7 +1557,6 @@ subroutine codes_get_api_version(api_version, status)
|
|||
end if
|
||||
end subroutine codes_get_api_version
|
||||
|
||||
|
||||
!> Get the error message given an error code
|
||||
!>
|
||||
!> @param error error code
|
||||
|
@ -1871,7 +1863,6 @@ subroutine codes_set_string_array ( msgid, key, value, status )
|
|||
|
||||
end subroutine codes_set_string_array
|
||||
|
||||
|
||||
!> Get the integer array of values for a key from a message.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -2103,7 +2094,6 @@ subroutine codes_get_real8_array ( msgid, key, value, status )
|
|||
end if
|
||||
end subroutine codes_get_real8_array
|
||||
|
||||
|
||||
!> Get a real(4) value of specified index from an array key.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -2125,7 +2115,6 @@ subroutine codes_get_real4_element ( msgid, key, kindex,value, status )
|
|||
call grib_get_real4_element(msgid, key, kindex, value, status)
|
||||
end subroutine codes_get_real4_element
|
||||
|
||||
|
||||
!> Get a real(8) value of specified index from an array key.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -2147,7 +2136,6 @@ subroutine codes_get_real8_element ( msgid, key, kindex,value, status )
|
|||
call grib_get_real8_element(msgid, key, kindex, value, status)
|
||||
end subroutine codes_get_real8_element
|
||||
|
||||
|
||||
!> Get the real(4) values whose indexes are stored in the array "index" from an array key.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -2209,7 +2197,6 @@ subroutine codes_set_int ( msgid, key, value, status )
|
|||
call grib_set_int(msgid, key, value, status)
|
||||
end subroutine codes_set_int
|
||||
|
||||
|
||||
!> Set the integer value for a key in a message.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -2229,7 +2216,6 @@ subroutine codes_set_long ( msgid, key, value, status )
|
|||
call grib_set_long(msgid, key, value, status)
|
||||
end subroutine codes_set_long
|
||||
|
||||
|
||||
!> Set the real(4) value for a key in a message.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -2268,7 +2254,6 @@ subroutine codes_set_real8 ( msgid, key, value, status )
|
|||
call grib_set_real8(msgid, key, value, status)
|
||||
end subroutine codes_set_real8
|
||||
|
||||
|
||||
!> Set the integers values for an array key in a message.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -2444,7 +2429,6 @@ subroutine codes_get_message_size_int ( msgid, nbytes, status)
|
|||
call grib_get_message_size_int(msgid, nbytes, status)
|
||||
end subroutine codes_get_message_size_int
|
||||
|
||||
|
||||
!> Get the size of a coded message.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -2513,7 +2497,6 @@ subroutine codes_grib_multi_write ( multigribid, ifile , status)
|
|||
call grib_multi_write(multigribid, ifile, status)
|
||||
end subroutine codes_grib_multi_write
|
||||
|
||||
|
||||
!> Append a single field grib message to a multi field grib message.
|
||||
!> Only the sections with section number greather or equal "startsection" are copied from the input single message to the multi field output grib.
|
||||
!>
|
||||
|
@ -2605,7 +2588,6 @@ subroutine codes_grib_find_nearest_single(gribid,is_lsm, &
|
|||
value, distance, kindex, status)
|
||||
end subroutine codes_grib_find_nearest_single
|
||||
|
||||
|
||||
!> Find the 4 nearest points of a latitude longitude point.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -2641,7 +2623,6 @@ subroutine codes_grib_find_nearest_four_single(gribid,is_lsm, &
|
|||
value, distance, kindex, status)
|
||||
end subroutine codes_grib_find_nearest_four_single
|
||||
|
||||
|
||||
!> Turn on the support for multiple fields in a single message.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -2765,7 +2746,6 @@ subroutine codes_skip_read_only ( iterid, status )
|
|||
call grib_skip_read_only(iterid, status)
|
||||
end subroutine codes_skip_read_only
|
||||
|
||||
|
||||
!> Set the definition path
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -2796,7 +2776,6 @@ subroutine codes_set_samples_path ( path, status )
|
|||
call grib_set_samples_path(path, status)
|
||||
end subroutine codes_set_samples_path
|
||||
|
||||
|
||||
subroutine codes_julian_to_datetime(jd, year, month, day, hour, minute, second, status)
|
||||
real(kind=kindOfDouble), intent(in) :: jd
|
||||
integer(kind=kindOfLong), intent(out) :: year, month, day, hour, minute, second
|
||||
|
@ -2881,5 +2860,4 @@ subroutine codes_bufr_multi_element_constant_arrays_off (status )
|
|||
|
||||
end subroutine codes_bufr_multi_element_constant_arrays_off
|
||||
|
||||
|
||||
end module eccodes
|
||||
|
|
|
@ -21,7 +21,6 @@ module grib_api
|
|||
real(8), parameter, public :: GRIB_MISSING_DOUBLE = -1.D+100
|
||||
integer(4), parameter, public :: GRIB_MISSING_LONG = 2147483647
|
||||
|
||||
|
||||
!> Create a new message in memory from an integer or character array containting the coded message.
|
||||
!>
|
||||
!> The message can be accessed through its gribid and it will be available\n
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
! 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.
|
||||
|
||||
|
||||
!> Get the distinct values of the key in argument contained in the index. The key must belong to the index.
|
||||
!>
|
||||
!>
|
||||
|
@ -103,7 +102,6 @@
|
|||
grib_get_real8_array
|
||||
end interface grib_get
|
||||
|
||||
|
||||
!> Get the size of an array key.
|
||||
!>
|
||||
!> To get the size of a key representing an array.
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
! 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.
|
||||
|
||||
|
||||
!> Get the distinct values of the key in argument contained in the index. The key must belong to the index.
|
||||
!>
|
||||
!>
|
||||
|
|
|
@ -1338,7 +1338,6 @@
|
|||
end if
|
||||
end subroutine any_new_from_file
|
||||
|
||||
|
||||
!> Create a new message in memory from a character array containting the coded message.
|
||||
!>
|
||||
!> The message can be accessed through its gribid and it will be available\n
|
||||
|
@ -1432,7 +1431,6 @@
|
|||
end if
|
||||
end subroutine grib_new_from_samples
|
||||
|
||||
|
||||
!> Free the memory for the message referred as gribid.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -1554,7 +1552,6 @@
|
|||
call grib_f_check(status, caller, string)
|
||||
end subroutine grib_check
|
||||
|
||||
|
||||
!> Get latitudes/longitudes/data values (real(4)).
|
||||
!>
|
||||
!> Latitudes, longitudes, data values arrays are returned.
|
||||
|
@ -2041,7 +2038,6 @@
|
|||
end if
|
||||
end subroutine grib_get_string
|
||||
|
||||
|
||||
!> Get the integer array of values for a key from a grib message.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -3107,7 +3103,6 @@
|
|||
end if
|
||||
end subroutine grib_skip_coded
|
||||
|
||||
|
||||
!> Skip the duplicated keys in a keys iterator.
|
||||
!>
|
||||
!> In case of error, if the status parameter (optional) is not given, the program will
|
||||
|
@ -3131,7 +3126,6 @@
|
|||
end if
|
||||
end subroutine grib_skip_duplicates
|
||||
|
||||
|
||||
!> Skip the read_only keys in a keys iterator.
|
||||
!>
|
||||
!> Read only keys cannot be set.
|
||||
|
|
|
@ -324,7 +324,7 @@ static int pack_double(grib_accessor* a, const double* val, size_t* len)
|
|||
grib_accessor_data_ccsds_packing* self = (grib_accessor_data_ccsds_packing*)a;
|
||||
|
||||
grib_handle* hand = grib_handle_of_accessor(a);
|
||||
int err = GRIB_SUCCESS, i = 0;
|
||||
int err = GRIB_SUCCESS, i = 0, is_constant_field = 0;
|
||||
size_t buflen = 0;
|
||||
|
||||
unsigned char* buf = NULL;
|
||||
|
@ -373,7 +373,23 @@ static int pack_double(grib_accessor* a, const double* val, size_t* len)
|
|||
return GRIB_SUCCESS;
|
||||
}
|
||||
|
||||
if (bits_per_value == 0) { /* constant field */
|
||||
max = val[0];
|
||||
min = max;
|
||||
for (i = 1; i < n_vals; i++) {
|
||||
if (val[i] > max) max = val[i];
|
||||
else if (val[i] < min) min = val[i];
|
||||
}
|
||||
|
||||
if (min == max) {
|
||||
is_constant_field = 1;
|
||||
} else {
|
||||
if (bits_per_value == 0) {
|
||||
/* ECC-1202: A non-constant field with bitsPerValue==0! */
|
||||
bits_per_value = 24; /* Set sane value */
|
||||
}
|
||||
}
|
||||
|
||||
if (is_constant_field) {
|
||||
#ifdef DEBUG
|
||||
for (i = 1; i < n_vals; i++) {
|
||||
Assert(val[i] == val[0]);
|
||||
|
@ -401,15 +417,6 @@ static int pack_double(grib_accessor* a, const double* val, size_t* len)
|
|||
return err;
|
||||
|
||||
d = grib_power(decimal_scale_factor, 10);
|
||||
|
||||
max = val[0];
|
||||
min = max;
|
||||
for (i = 1; i < n_vals; i++) {
|
||||
if (val[i] > max)
|
||||
max = val[i];
|
||||
else if (val[i] < min)
|
||||
min = val[i];
|
||||
}
|
||||
min *= d;
|
||||
max *= d;
|
||||
|
||||
|
|
117
src/grib_util.c
117
src/grib_util.c
|
@ -11,6 +11,7 @@
|
|||
#include "grib_api_internal.h"
|
||||
#include <float.h>
|
||||
|
||||
#define STR_EQUAL(s1, s2) (strcmp((s1), (s2)) == 0)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -888,8 +889,8 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
size_t count = 0;
|
||||
int i;
|
||||
long editionNumber;
|
||||
grib_handle* outh = NULL;
|
||||
grib_handle* tmp = NULL;
|
||||
grib_handle* h_out = NULL;
|
||||
grib_handle* h_sample = NULL;
|
||||
const char* grid_type = NULL;
|
||||
char name[1024];
|
||||
char input_grid_type[100];
|
||||
|
@ -919,8 +920,7 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
/* Get edition number from input handle */
|
||||
if ((*err = grib_get_long(h, "edition", &editionNumber)) != 0) {
|
||||
grib_context* c = grib_context_get_default();
|
||||
if (c->write_on_fail)
|
||||
grib_write_message(h, "error.grib", "w");
|
||||
if (c->write_on_fail) grib_write_message(h, "error.grib", "w");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1026,10 +1026,8 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
|
||||
if ((*err = grib_set_values(h, values, count)) != 0) {
|
||||
fprintf(stderr, "GRIB_UTIL_SET_SPEC: Cannot set values %s\n", grib_get_error_message(*err));
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
if (values[i].error)
|
||||
fprintf(stderr, " %s %s\n", values[i].name, grib_get_error_message(values[i].error));
|
||||
if (values[i].error) fprintf(stderr, " %s %s\n", values[i].name, grib_get_error_message(values[i].error));
|
||||
goto cleanup;
|
||||
}
|
||||
if (h->context->debug == -1) {
|
||||
|
@ -1090,7 +1088,7 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
} /* flags & GRIB_UTIL_SET_SPEC_FLAGS_ONLY_PACKING */
|
||||
|
||||
grid_type = get_grid_type_name(spec->grid_type);
|
||||
if (grid_type == NULL) {
|
||||
|
@ -1143,9 +1141,9 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
}
|
||||
}
|
||||
|
||||
/* TODO: recycle tmp handle */
|
||||
tmp = grib_handle_new_from_samples(NULL, name);
|
||||
if (!tmp) {
|
||||
/* TODO: recycle h_sample handle */
|
||||
h_sample = grib_handle_new_from_samples(NULL, name);
|
||||
if (!h_sample) {
|
||||
*err = GRIB_INVALID_FILE;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1447,6 +1445,8 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
}
|
||||
}
|
||||
|
||||
/* ECC-1201: case of IEEE input ?? */
|
||||
|
||||
switch (packing_spec->accuracy) {
|
||||
case GRIB_UTIL_ACCURACY_SAME_BITS_PER_VALUES_AS_INPUT: {
|
||||
long bitsPerValue = 0;
|
||||
|
@ -1470,7 +1470,7 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
|
||||
default:
|
||||
fprintf(stderr, "invalid packing_spec->accuracy = %ld\n", (long)packing_spec->accuracy);
|
||||
grib_handle_delete(tmp);
|
||||
grib_handle_delete(h_sample);
|
||||
*err = GRIB_INTERNAL_ERROR;
|
||||
goto cleanup;
|
||||
break;
|
||||
|
@ -1498,13 +1498,13 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
}
|
||||
}
|
||||
/* grib_write_message(h,"input.grib","w"); */
|
||||
/* grib_write_message(tmp,"geo.grib","w"); */
|
||||
/* copy product and local sections from h to tmp handle and store in outh */
|
||||
if ((outh = grib_util_sections_copy(h, tmp, GRIB_SECTION_PRODUCT | GRIB_SECTION_LOCAL, err)) == NULL) {
|
||||
/* grib_write_message(h_sample,"geo.grib","w"); */
|
||||
/* copy product and local sections from h to h_sample handle and store in h_out */
|
||||
if ((h_out = grib_util_sections_copy(h, h_sample, GRIB_SECTION_PRODUCT | GRIB_SECTION_LOCAL, err)) == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
grib_handle_delete(tmp);
|
||||
grib_handle_delete(h_sample);
|
||||
Assert(*err == 0);
|
||||
|
||||
/* Set "pl" array if provided (For reduced Gaussian grids) */
|
||||
|
@ -1520,7 +1520,7 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
}
|
||||
|
||||
if (spec->pl_size != 0 && (spec->grid_type == GRIB_UTIL_GRID_SPEC_REDUCED_GG || spec->grid_type == GRIB_UTIL_GRID_SPEC_REDUCED_ROTATED_GG)) {
|
||||
*err = grib_set_long_array(outh, "pl", spec->pl, spec->pl_size);
|
||||
*err = grib_set_long_array(h_out, "pl", spec->pl, spec->pl_size);
|
||||
if (*err) {
|
||||
fprintf(stderr, "SET_GRID_DATA_DESCRIPTION: Cannot set pl %s\n", grib_get_error_message(*err));
|
||||
goto cleanup;
|
||||
|
@ -1544,32 +1544,30 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
|
||||
/* Apply adjustments to bounding box if needed */
|
||||
if (expandBoundingBox) {
|
||||
if ((*err = expand_bounding_box(outh, values, count)) != 0) {
|
||||
if ((*err = expand_bounding_box(h_out, values, count)) != 0) {
|
||||
fprintf(stderr, "SET_GRID_DATA_DESCRIPTION: Cannot expand bounding box: %s\n", grib_get_error_message(*err));
|
||||
if (h->context->write_on_fail)
|
||||
grib_write_message(outh, "error.grib", "w");
|
||||
grib_write_message(h_out, "error.grib", "w");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (convertEditionEarlier && packing_spec->editionNumber > 1) {
|
||||
*err = grib_set_long(outh, "edition", packing_spec->editionNumber);
|
||||
*err = grib_set_long(h_out, "edition", packing_spec->editionNumber);
|
||||
if (*err) {
|
||||
fprintf(stderr, "SET_GRID_DATA_DESCRIPTION: Cannot convert to edition %ld.\n", packing_spec->editionNumber);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if ((*err = grib_set_values(outh, values, count)) != 0) {
|
||||
if ((*err = grib_set_values(h_out, values, count)) != 0) {
|
||||
fprintf(stderr, "SET_GRID_DATA_DESCRIPTION: Cannot set key values: %s\n", grib_get_error_message(*err));
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
if (values[i].error)
|
||||
fprintf(stderr, " %s %s\n", values[i].name, grib_get_error_message(values[i].error));
|
||||
if (values[i].error) fprintf(stderr, " %s %s\n", values[i].name, grib_get_error_message(values[i].error));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((*err = grib_set_double_array(outh, "values", data_values, data_values_count)) != 0) {
|
||||
if ((*err = grib_set_double_array(h_out, "values", data_values, data_values_count)) != 0) {
|
||||
FILE* ferror;
|
||||
size_t ii, lcount;
|
||||
grib_context* c = grib_context_get_default();
|
||||
|
@ -1588,67 +1586,66 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
}
|
||||
fprintf(ferror, "%g }", data_values[data_values_count - 1]);
|
||||
fclose(ferror);
|
||||
if (c->write_on_fail)
|
||||
grib_write_message(outh, "error.grib", "w");
|
||||
if (c->write_on_fail) grib_write_message(h_out, "error.grib", "w");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* grib_write_message(outh,"h.grib","w"); */
|
||||
/* grib_write_message(h_out,"h.grib","w"); */
|
||||
/* if the field is empty GRIBEX is packing as simple*/
|
||||
/* if (!strcmp(input_packing_type,"grid_simple_matrix")) {
|
||||
long numberOfValues;
|
||||
grib_get_long(outh,"numberOfValues",&numberOfValues);
|
||||
grib_get_long(h_out,"numberOfValues",&numberOfValues);
|
||||
if (numberOfValues==0) {
|
||||
slen=11;
|
||||
grib_set_string(outh,"packingType","grid_simple",&slen);
|
||||
grib_set_string(h_out,"packingType","grid_simple",&slen);
|
||||
}
|
||||
} */
|
||||
|
||||
if (grib1_high_resolution_fix) {
|
||||
/* GRIB-863: must set increments to MISSING */
|
||||
/* increments are not coded in message but computed */
|
||||
if ((*err = grib_set_missing(outh, "iDirectionIncrement")) != 0) {
|
||||
if ((*err = grib_set_missing(h_out, "iDirectionIncrement")) != 0) {
|
||||
fprintf(stderr, "GRIB_UTIL_SET_SPEC: Cannot set Di to missing: %s\n", grib_get_error_message(*err));
|
||||
goto cleanup;
|
||||
}
|
||||
if ((*err = grib_set_missing(outh, "jDirectionIncrement")) != 0) {
|
||||
if ((*err = grib_set_missing(h_out, "jDirectionIncrement")) != 0) {
|
||||
fprintf(stderr, "GRIB_UTIL_SET_SPEC: Cannot set Dj to missing: %s\n", grib_get_error_message(*err));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/*grib_dump_content(outh, stdout,"debug", ~0, NULL);*/
|
||||
/*grib_dump_content(h_out, stdout,"debug", ~0, NULL);*/
|
||||
|
||||
/* convert to second_order if not constant field. (Also see ECC-326) */
|
||||
if (setSecondOrder) {
|
||||
int constant = 0;
|
||||
double missingValue = 0;
|
||||
grib_get_double(outh, "missingValue", &missingValue);
|
||||
grib_get_double(h_out, "missingValue", &missingValue);
|
||||
constant = is_constant_field(missingValue, data_values, data_values_count);
|
||||
|
||||
if (!constant) {
|
||||
if (editionNumber == 1) {
|
||||
long numberOfGroups = 0;
|
||||
grib_handle* htmp = grib_handle_clone(outh);
|
||||
grib_handle* htmp = grib_handle_clone(h_out);
|
||||
|
||||
slen = 17;
|
||||
grib_set_string(htmp, "packingType", "grid_second_order", &slen);
|
||||
grib_get_long(htmp, "numberOfGroups", &numberOfGroups);
|
||||
/* GRIBEX is not able to decode overflown numberOfGroups with SPD */
|
||||
if (numberOfGroups > 65534 && outh->context->no_spd) {
|
||||
if (numberOfGroups > 65534 && h_out->context->no_spd) {
|
||||
slen = 24;
|
||||
grib_set_string(outh, "packingType", "grid_second_order_no_SPD", &slen);
|
||||
grib_set_string(h_out, "packingType", "grid_second_order_no_SPD", &slen);
|
||||
grib_handle_delete(htmp);
|
||||
}
|
||||
else {
|
||||
grib_handle_delete(outh);
|
||||
outh = htmp;
|
||||
grib_handle_delete(h_out);
|
||||
h_out = htmp;
|
||||
}
|
||||
}
|
||||
else {
|
||||
slen = 17;
|
||||
grib_set_string(outh, "packingType", "grid_second_order", &slen);
|
||||
*err = grib_set_double_array(outh, "values", data_values, data_values_count);
|
||||
grib_set_string(h_out, "packingType", "grid_second_order", &slen);
|
||||
*err = grib_set_double_array(h_out, "values", data_values, data_values_count);
|
||||
if (*err != GRIB_SUCCESS) {
|
||||
fprintf(stderr, "GRIB_UTIL_SET_SPEC: setting data values failed! %s\n", grib_get_error_message(*err));
|
||||
goto cleanup;
|
||||
|
@ -1656,21 +1653,21 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (outh->context->gribex_mode_on) {
|
||||
outh->context->gribex_mode_on = 0;
|
||||
grib_set_double_array(outh, "values", data_values, data_values_count);
|
||||
outh->context->gribex_mode_on = 1;
|
||||
if (h_out->context->gribex_mode_on) {
|
||||
h_out->context->gribex_mode_on = 0;
|
||||
grib_set_double_array(h_out, "values", data_values, data_values_count);
|
||||
h_out->context->gribex_mode_on = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (packing_spec->editionNumber && packing_spec->editionNumber != editionNumber) {
|
||||
*err = grib_set_long(outh, "edition", packing_spec->editionNumber);
|
||||
*err = grib_set_long(h_out, "edition", packing_spec->editionNumber);
|
||||
if (*err != GRIB_SUCCESS) {
|
||||
fprintf(stderr, "GRIB_UTIL_SET_SPEC: Failed to change edition to %ld: %s\n",
|
||||
packing_spec->editionNumber, grib_get_error_message(*err));
|
||||
if (h->context->write_on_fail)
|
||||
grib_write_message(outh, "error.grib", "w");
|
||||
grib_write_message(h_out, "error.grib", "w");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
@ -1679,7 +1676,7 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
/* ECC-353 */
|
||||
/* JPEG packing is not available in GRIB edition 1 and has to be done AFTER we set data values */
|
||||
if (setJpegPacking == 1) {
|
||||
*err = grib_set_string(outh, "packingType", "grid_jpeg", &slen);
|
||||
*err = grib_set_string(h_out, "packingType", "grid_jpeg", &slen);
|
||||
if (*err != GRIB_SUCCESS) {
|
||||
fprintf(stderr, "GRIB_UTIL_SET_SPEC: Failed to change packingType to JPEG: %s\n",
|
||||
grib_get_error_message(*err));
|
||||
|
@ -1687,7 +1684,7 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
}
|
||||
}
|
||||
if (setCcsdsPacking == 1) {
|
||||
*err = grib_set_string(outh, "packingType", "grid_ccsds", &slen);
|
||||
*err = grib_set_string(h_out, "packingType", "grid_ccsds", &slen);
|
||||
if (*err != GRIB_SUCCESS) {
|
||||
fprintf(stderr, "GRIB_UTIL_SET_SPEC: Failed to change packingType to CCSDS: %s\n",
|
||||
grib_get_error_message(*err));
|
||||
|
@ -1697,7 +1694,7 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
}
|
||||
|
||||
if (packing_spec->deleteLocalDefinition) {
|
||||
grib_set_long(outh, "deleteLocalDefinition", 1);
|
||||
grib_set_long(h_out, "deleteLocalDefinition", 1);
|
||||
}
|
||||
|
||||
/* ECC-445 */
|
||||
|
@ -1705,36 +1702,32 @@ grib_handle* grib_util_set_spec2(grib_handle* h,
|
|||
Assert(!global_grid); /* ECC-576: "global" should not be set */
|
||||
}
|
||||
|
||||
if ((*err = check_geometry(outh, spec, data_values_count, global_grid)) != GRIB_SUCCESS) {
|
||||
if ((*err = check_geometry(h_out, spec, data_values_count, global_grid)) != GRIB_SUCCESS) {
|
||||
fprintf(stderr, "GRIB_UTIL_SET_SPEC: Geometry check failed! %s\n", grib_get_error_message(*err));
|
||||
if (h->context->write_on_fail)
|
||||
grib_write_message(outh, "error.grib", "w");
|
||||
grib_write_message(h_out, "error.grib", "w");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Disable check: need to re-examine GRIB-864 */
|
||||
#if 0
|
||||
if ( (*err = check_handle_against_spec(outh, editionNumber, spec, global_grid)) != GRIB_SUCCESS)
|
||||
{
|
||||
|
||||
if ( (*err = check_handle_against_spec(h_out, editionNumber, spec, global_grid)) != GRIB_SUCCESS) {
|
||||
grib_context* c=grib_context_get_default();
|
||||
fprintf(stderr,"GRIB_UTIL_SET_SPEC: Geometry check failed! %s\n", grib_get_error_message(*err));
|
||||
if (editionNumber == 1) {
|
||||
fprintf(stderr,"Note: in GRIB edition 1 latitude and longitude values cannot be represented with sub-millidegree precision.\n");
|
||||
}
|
||||
if (c->write_on_fail)
|
||||
grib_write_message(outh,"error.grib","w");
|
||||
if (c->write_on_fail) grib_write_message(h_out,"error.grib","w");
|
||||
goto cleanup;
|
||||
}
|
||||
#endif
|
||||
if (h->context->debug == -1)
|
||||
fprintf(stderr, "ECCODES DEBUG: grib_util_set_spec end\n");
|
||||
if (h->context->debug == -1) fprintf(stderr, "ECCODES DEBUG: grib_util_set_spec end\n");
|
||||
|
||||
return outh;
|
||||
return h_out;
|
||||
|
||||
cleanup:
|
||||
if (outh)
|
||||
grib_handle_delete(outh);
|
||||
if (h_out)
|
||||
grib_handle_delete(h_out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ list(APPEND test_bins
|
|||
gauss_sub
|
||||
grib_nearest_test
|
||||
grib_util_set_spec
|
||||
grib_check_param_concepts
|
||||
grib_local_MeteoFrance
|
||||
grib_2nd_order_numValues
|
||||
grib_optimize_scaling
|
||||
|
|
|
@ -32,10 +32,8 @@ ${tools_dir}/grib_set -r -s packingType=grid_ccsds $outfile1 $outfile2
|
|||
${tools_dir}/grib_compare -b $BLACKLIST $outfile1 $outfile2 > $REDIRECT
|
||||
|
||||
templateNumber=`${tools_dir}/grib_get -p dataRepresentationTemplateNumber $outfile2`
|
||||
|
||||
if [ $templateNumber -ne 42 ]
|
||||
then
|
||||
echo dataRepresentationTemplateNumber=$templateNumber
|
||||
if [ $templateNumber -ne 42 ]; then
|
||||
echo "dataRepresentationTemplateNumber=$templateNumber. Should be 42!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -58,7 +56,8 @@ res3=`${tools_dir}/grib_get '-F%1.2f' -p min,max,avg $outfile2`
|
|||
|
||||
rm -f $outfile1 $outfile2
|
||||
|
||||
# ECC-297
|
||||
# ECC-297: Basic support
|
||||
# --------------------------------------
|
||||
infile=${data_dir}/tigge_ecmwf.grib2
|
||||
outfile1=$infile.tmp_ccsds.1
|
||||
outfile2=$infile.tmp_ccsds.2
|
||||
|
@ -68,10 +67,21 @@ ${tools_dir}/grib_set -r -s packingType=grid_ccsds $outfile1 $outfile2
|
|||
${tools_dir}/grib_compare -c data:n $outfile1 $outfile2
|
||||
|
||||
# ECC-477: redundant error message during conversion
|
||||
# ---------------------------------------------------
|
||||
infile=${data_dir}/ccsds.grib2
|
||||
rm -f $outfile2
|
||||
${tools_dir}/grib_set -r -s packingType=grid_simple $infile $outfile1 >$outfile2 2>&1
|
||||
# there should be no error messages printed (to stdout or stderr)
|
||||
[ ! -s $outfile2 ]
|
||||
|
||||
# ECC-1202: Check input packingType=grid_ieee
|
||||
# --------------------------------------------
|
||||
infile=${data_dir}/grid_ieee.grib
|
||||
${tools_dir}/grib_set -r -s packingType=grid_ccsds $infile $outfile1
|
||||
grib_check_key_equals $outfile1 packingType grid_ccsds
|
||||
${tools_dir}/grib_set -r -s packingType=grid_simple $infile $outfile2
|
||||
${tools_dir}/grib_compare -c data:n $outfile1 $outfile2
|
||||
|
||||
|
||||
# Clean up
|
||||
rm -f $outfile1 $outfile2
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* (C) Copyright 2005- 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Check GRIB2 parameter concept file e.g. shortName.def, paramId.def
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "grib_api_internal.h"
|
||||
|
||||
typedef struct grib_expression_long {
|
||||
grib_expression base;
|
||||
long value;
|
||||
} grib_expression_long;
|
||||
|
||||
typedef struct grib_expression_functor {
|
||||
grib_expression base;
|
||||
char* name;
|
||||
grib_arguments* args;
|
||||
} grib_expression_functor;
|
||||
|
||||
typedef struct grib_expression_string {
|
||||
grib_expression base;
|
||||
char* value;
|
||||
} grib_expression_string;
|
||||
|
||||
static int type_of_surface_missing(const char* value)
|
||||
{
|
||||
/* Surface Type is Code Table 4.5 in which 255 is the same as missing */
|
||||
if (strcmp(value, "missing") == 0 || strcmp(value, "255") == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int scale_factor_missing(const char* value)
|
||||
{
|
||||
/* Scale factor is one octet so 255 is the same as missing */
|
||||
if (strcmp(value, "missing") == 0 || strcmp(value, "255") == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int grib_check_param_concepts(const char* key, const char* filename)
|
||||
{
|
||||
grib_concept_value* concept_value = grib_parse_concept_file(NULL, filename);
|
||||
if (!concept_value)
|
||||
return GRIB_IO_PROBLEM;
|
||||
|
||||
while (concept_value) {
|
||||
grib_concept_condition* concept_condition = concept_value->conditions;
|
||||
/* Convention:
|
||||
* -1 key not present
|
||||
* 0 key present and not missing
|
||||
* 1 key present and missing
|
||||
*/
|
||||
int scaleFactor1Missing = -1, scaleFactor2Missing = -1;
|
||||
int scaledValue1Missing = -1, scaledValue2Missing = -1;
|
||||
int type1Missing = -1, type2Missing = -1;
|
||||
int err = 0;
|
||||
/* concept_value->name is the value of the key e.g. 151163 */
|
||||
while (concept_condition) {
|
||||
char condition_value[512] = {0,};
|
||||
grib_expression* expression = concept_condition->expression;
|
||||
const char* condition_name = concept_condition->name;
|
||||
/* condition_name is discipline, parameterCategory etc. */
|
||||
if (strcmp(expression->cclass->name, "long") == 0) {
|
||||
grib_expression_long* el = (grib_expression_long*)expression;
|
||||
sprintf(condition_value, "%ld", el->value);
|
||||
}
|
||||
else if (strcmp(expression->cclass->name, "functor") == 0) {
|
||||
grib_expression_functor* ef = (grib_expression_functor*)expression;
|
||||
sprintf(condition_value, "%s", ef->name);
|
||||
}
|
||||
else if (strcmp(expression->cclass->name, "string") == 0) {
|
||||
grib_expression_string* es = (grib_expression_string*)expression;
|
||||
sprintf(condition_value, "%s", es->value);
|
||||
}
|
||||
else {
|
||||
Assert(0);
|
||||
}
|
||||
if (strcmp(condition_name, "typeOfFirstFixedSurface") == 0) {
|
||||
type1Missing = type_of_surface_missing(condition_value);
|
||||
}
|
||||
if (strcmp(condition_name, "typeOfSecondFixedSurface") == 0) {
|
||||
type2Missing = type_of_surface_missing(condition_value);
|
||||
}
|
||||
if (strcmp(condition_name, "scaleFactorOfFirstFixedSurface") == 0) {
|
||||
scaleFactor1Missing = scale_factor_missing(condition_value);
|
||||
}
|
||||
if (strcmp(condition_name, "scaleFactorOfSecondFixedSurface") == 0) {
|
||||
scaleFactor2Missing = scale_factor_missing(condition_value);
|
||||
}
|
||||
if (strcmp(condition_name, "scaledValueOfFirstFixedSurface") == 0) {
|
||||
scaledValue1Missing = (strcmp(condition_value, "missing") == 0);
|
||||
}
|
||||
if (strcmp(condition_name, "scaledValueOfSecondFixedSurface") == 0) {
|
||||
scaledValue2Missing = (strcmp(condition_value, "missing") == 0);
|
||||
}
|
||||
|
||||
concept_condition = concept_condition->next;
|
||||
}
|
||||
/* Now check the scale factor/value pairs */
|
||||
if (type1Missing == 1 && scaleFactor1Missing == 0 && scaledValue1Missing == 0) err = 1;
|
||||
if (type2Missing == 1 && scaleFactor2Missing == 0 && scaledValue2Missing == 0) err = 1;
|
||||
if (scaleFactor1Missing == 1 && scaledValue1Missing == 0) err = 1;
|
||||
if (scaleFactor1Missing == 0 && scaledValue1Missing == 1) err = 1;
|
||||
if (scaleFactor2Missing == 1 && scaledValue2Missing == 0) err = 1;
|
||||
if (scaleFactor2Missing == 0 && scaledValue2Missing == 1) err = 1;
|
||||
if (err) {
|
||||
fprintf(stderr,
|
||||
"Error: Mismatched type of surface, scale factor, scaled value keys for %s='%s'.\n"
|
||||
" If the type of surface is missing so should its scaled keys\n"
|
||||
" If the scale factor is missing so should the scaled value and vice versa\n",
|
||||
key, concept_value->name);
|
||||
return GRIB_INVALID_KEY_VALUE;
|
||||
}
|
||||
concept_value = concept_value->next;
|
||||
}
|
||||
return GRIB_SUCCESS;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int err = 0;
|
||||
const char* concepts_key = argv[1];
|
||||
const char* concepts_filename = argv[2];
|
||||
|
||||
assert(argc == 3);
|
||||
err = grib_check_param_concepts(concepts_key, concepts_filename);
|
||||
if (err) return err;
|
||||
|
||||
printf("ALL OK\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -10,12 +10,21 @@
|
|||
|
||||
. ./include.sh
|
||||
|
||||
REDIRECT=/dev/null
|
||||
|
||||
# This script will check the following concept files:
|
||||
# name.def paramId.def shortName.def units.def cfVarName.def
|
||||
#
|
||||
# Do various checks on the concepts files
|
||||
#
|
||||
|
||||
# First check the GRIB2 paramId.def and shortName.def
|
||||
# ----------------------------------------------------
|
||||
$EXEC ${test_dir}/grib_check_param_concepts paramId $ECCODES_DEFINITION_PATH/grib2/paramId.def
|
||||
$EXEC ${test_dir}/grib_check_param_concepts paramId $ECCODES_DEFINITION_PATH/grib2/localConcepts/ecmf/paramId.def
|
||||
|
||||
$EXEC ${test_dir}/grib_check_param_concepts shortName $ECCODES_DEFINITION_PATH/grib2/shortName.def
|
||||
$EXEC ${test_dir}/grib_check_param_concepts shortName $ECCODES_DEFINITION_PATH/grib2/localConcepts/ecmf/shortName.def
|
||||
|
||||
|
||||
# Check the group: name.def paramId.def shortName.def units.def cfVarName.def
|
||||
# ----------------------------------------------------------------------------
|
||||
# Check whether the Test::More Perl module is available
|
||||
set +e
|
||||
perl -e 'use Test::More;'
|
||||
|
|
|
@ -1475,7 +1475,6 @@ static void test_concept_condition_strings()
|
|||
|
||||
err = get_concept_condition_string(h, "gridType", NULL, result);
|
||||
Assert(!err);
|
||||
/*printf("%s\n", result);*/
|
||||
Assert(strcmp(result, "gridDefinitionTemplateNumber=0,PLPresent=0") == 0);
|
||||
|
||||
err = get_concept_condition_string(h, "stepType", NULL, result);
|
||||
|
|
Loading…
Reference in New Issue