mirror of https://github.com/ecmwf/eccodes.git
Improve the grib_check_gaussian_grid tool error reporting
This commit is contained in:
parent
abb85e3481
commit
a774089f1f
|
@ -9,9 +9,25 @@
|
||||||
|
|
||||||
. ./include.sh
|
. ./include.sh
|
||||||
|
|
||||||
|
label="grib_check_gaussian_grids"
|
||||||
|
temp=temp.$label.grib
|
||||||
|
|
||||||
|
|
||||||
# Check all sample GRIBs with a Gaussian grid
|
# Check all sample GRIBs with a Gaussian grid
|
||||||
samples_dir=$ECCODES_SAMPLES_PATH
|
samples_dir=$ECCODES_SAMPLES_PATH
|
||||||
for gg in ${samples_dir}/reduced_gg_* ${samples_dir}/regular_gg_*; do
|
for gg in ${samples_dir}/reduced_gg_* ${samples_dir}/regular_gg_*; do
|
||||||
${tools_dir}/grib_check_gaussian_grid $gg >/dev/null
|
${tools_dir}/grib_check_gaussian_grid $gg >/dev/null
|
||||||
grib_check_key_equals $gg "global" 1
|
grib_check_key_equals $gg "global" 1
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Set wrong angle and re-test. Should fail
|
||||||
|
input=$samples_dir/reduced_gg_pl_1280_grib2.tmpl
|
||||||
|
${tools_dir}/grib_set -s longitudeOfLastGridPoint=359929680 $input $temp
|
||||||
|
set +e
|
||||||
|
${tools_dir}/grib_check_gaussian_grid -v $temp
|
||||||
|
status=$?
|
||||||
|
set -e
|
||||||
|
[ $status -eq 1 ]
|
||||||
|
|
||||||
|
|
||||||
|
rm -f $temp
|
||||||
|
|
|
@ -18,11 +18,13 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include "eccodes.h"
|
#include "eccodes.h"
|
||||||
|
|
||||||
#define STR_EQUAL(s1, s2) (strcmp((s1), (s2)) == 0)
|
#define STR_EQUAL(s1, s2) (strcmp((s1), (s2)) == 0)
|
||||||
|
|
||||||
int exit_on_error = 1; /* By default exit if any check fails */
|
int exit_on_error = 1; /* By default exit if any check fails */
|
||||||
|
int verbose = 0; /* By default quiet unless errors */
|
||||||
int error_count = 0;
|
int error_count = 0;
|
||||||
|
|
||||||
int DBL_EQUAL(double d1, double d2, double tolerance)
|
int DBL_EQUAL(double d1, double d2, double tolerance)
|
||||||
|
@ -32,22 +34,26 @@ int DBL_EQUAL(double d1, double d2, double tolerance)
|
||||||
|
|
||||||
void usage(const char* prog)
|
void usage(const char* prog)
|
||||||
{
|
{
|
||||||
printf("Usage: %s [-f] grib_file grib_file ...\n\n",prog);
|
printf("Usage: %s [-f] [-v] grib_file grib_file ...\n\n",prog);
|
||||||
printf("Check geometry of GRIB fields with a Gaussian Grid.\n");
|
printf("Check geometry of GRIB fields with a Gaussian Grid.\n");
|
||||||
printf("(The grid is assumed to be GLOBAL)\n\n");
|
printf("(The grid is assumed to be GLOBAL)\n\n");
|
||||||
printf("Options:\n");
|
printf("Options:\n");
|
||||||
printf("-f Do not exit on first error\n");
|
printf(" -f Do not exit on first error\n");
|
||||||
|
printf(" -v Verbose\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print an error message and die */
|
/* Print an error message and optionally die */
|
||||||
void error(const char* fmt, ...)
|
void error(const char* filename, int msg_num, const char* fmt, ...)
|
||||||
{
|
{
|
||||||
char buf[1024] = {0,};
|
char buf[1024] = {0,};
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start(list,fmt);
|
va_start(list,fmt);
|
||||||
sprintf(buf, " %s", fmt); /* indent a bit */
|
if(verbose)
|
||||||
|
sprintf(buf, " Error: %s", fmt); /* indent a bit */
|
||||||
|
else
|
||||||
|
sprintf(buf, "Error: %s #%d: %s", filename, msg_num, fmt);
|
||||||
vfprintf(stderr, buf, list);
|
vfprintf(stderr, buf, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
|
|
||||||
|
@ -65,17 +71,32 @@ double get_precision(long edition)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_regular_file(const char* path)
|
||||||
|
{
|
||||||
|
struct stat s;
|
||||||
|
int stat_val = stat(path,&s);
|
||||||
|
if (stat_val != 0) return 0; /*error doing stat*/
|
||||||
|
return S_ISREG( s.st_mode );
|
||||||
|
}
|
||||||
|
|
||||||
int process_file(const char* filename)
|
int process_file(const char* filename)
|
||||||
{
|
{
|
||||||
int err = 0, msg_num = 0;
|
int err = 0, msg_num = 0;
|
||||||
codes_handle *h = NULL;
|
codes_handle *h = NULL;
|
||||||
|
FILE* in = NULL;
|
||||||
FILE* in = fopen(filename, "r");
|
|
||||||
if(!in) {
|
if (!is_regular_file(filename)) {
|
||||||
error("ERROR: unable to open input file %s\n",filename);
|
if(verbose) printf(" WARNING: '%s' not a regular file! Ignoring\n", filename);
|
||||||
|
return GRIB_IO_PROBLEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Checking file %s\n", filename);
|
in = fopen(filename, "r");
|
||||||
|
if(!in) {
|
||||||
|
fprintf(stderr, "ERROR: unable to open input file %s\n",filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(verbose) printf("Checking file %s\n", filename);
|
||||||
|
|
||||||
while ((h = codes_handle_new_from_file(0, in, PRODUCT_GRIB, &err)) != NULL )
|
while ((h = codes_handle_new_from_file(0, in, PRODUCT_GRIB, &err)) != NULL )
|
||||||
{
|
{
|
||||||
|
@ -91,7 +112,7 @@ int process_file(const char* filename)
|
||||||
if (err != CODES_SUCCESS) CODES_CHECK(err,0);
|
if (err != CODES_SUCCESS) CODES_CHECK(err,0);
|
||||||
++msg_num;
|
++msg_num;
|
||||||
CODES_CHECK(codes_get_long(h,"edition",&edition),0);
|
CODES_CHECK(codes_get_long(h,"edition",&edition),0);
|
||||||
printf(" Processing GRIB message #%d (edition=%ld)\n", msg_num, edition);
|
if(verbose) printf(" Processing GRIB message #%d (edition=%ld)\n", msg_num, edition);
|
||||||
|
|
||||||
len = 32;
|
len = 32;
|
||||||
CODES_CHECK(codes_get_string(h,"gridType",gridType,&len),0);
|
CODES_CHECK(codes_get_string(h,"gridType",gridType,&len),0);
|
||||||
|
@ -100,7 +121,7 @@ int process_file(const char* filename)
|
||||||
grid_ok = is_regular || is_reduced;
|
grid_ok = is_regular || is_reduced;
|
||||||
if( !grid_ok ) {
|
if( !grid_ok ) {
|
||||||
/*error("ERROR: gridType should be Reduced or Regular Gaussian Grid!\n");*/
|
/*error("ERROR: gridType should be Reduced or Regular Gaussian Grid!\n");*/
|
||||||
printf(" WARNING: gridType should be Reduced or Regular Gaussian Grid! Ignoring\n");
|
if(verbose) printf(" WARNING: gridType should be Reduced or Regular Gaussian Grid! Ignoring\n");
|
||||||
codes_handle_delete(h);
|
codes_handle_delete(h);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -117,20 +138,20 @@ int process_file(const char* filename)
|
||||||
angular_tolerance = get_precision(edition);
|
angular_tolerance = get_precision(edition);
|
||||||
|
|
||||||
if (N <= 0) {
|
if (N <= 0) {
|
||||||
error("ERROR: N should be > 0\n", N);
|
error(filename, msg_num, "N should be > 0\n", N);
|
||||||
}
|
}
|
||||||
if ( Nj != 2*N ) {
|
if ( Nj != 2*N ) {
|
||||||
error("ERROR: Nj is %ld but should be 2*N (%ld)\n", Nj, 2*N);
|
error(filename, msg_num, "Nj is %ld but should be 2*N (%ld)\n", Nj, 2*N);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lon1 != 0) {
|
if (lon1 != 0) {
|
||||||
error("ERROR: latitudeOfFirstGridPointInDegrees=%f but should be 0\n", lon1);
|
error(filename, msg_num, "latitudeOfFirstGridPointInDegrees=%f but should be 0\n", lon1);
|
||||||
}
|
}
|
||||||
expected_lon2 = 360.0 - 360.0/(4*N);
|
expected_lon2 = 360.0 - 360.0/(4*N);
|
||||||
|
|
||||||
/* Check first and last latitudes */
|
/* Check first and last latitudes */
|
||||||
if (lat1 != -lat2) {
|
if (lat1 != -lat2) {
|
||||||
error("ERROR: First latitude must be = last latitude but opposite in sign: lat1=%f, lat2=%f\n",
|
error(filename, msg_num, "First latitude must be = last latitude but opposite in sign: lat1=%f, lat2=%f\n",
|
||||||
lat1, lat2);
|
lat1, lat2);
|
||||||
}
|
}
|
||||||
/* Note: grib_get_gaussian_latitudes() assumes the 'lats' array has 2N elements! */
|
/* Note: grib_get_gaussian_latitudes() assumes the 'lats' array has 2N elements! */
|
||||||
|
@ -139,10 +160,10 @@ int process_file(const char* filename)
|
||||||
CODES_CHECK(codes_get_gaussian_latitudes(N,lats), 0);
|
CODES_CHECK(codes_get_gaussian_latitudes(N,lats), 0);
|
||||||
|
|
||||||
if (!DBL_EQUAL(lats[0], lat1, angular_tolerance)) {
|
if (!DBL_EQUAL(lats[0], lat1, angular_tolerance)) {
|
||||||
error("ERROR: latitudeOfFirstGridPointInDegrees=%f but should be %f\n", lat1, lats[0]);
|
error(filename, msg_num, "latitudeOfFirstGridPointInDegrees=%f but should be %f\n", lat1, lats[0]);
|
||||||
}
|
}
|
||||||
if (!DBL_EQUAL(lats[Nj-1], lat2, angular_tolerance)) {
|
if (!DBL_EQUAL(lats[Nj-1], lat2, angular_tolerance)) {
|
||||||
error("ERROR: latitudeOfLastGridPointInDegrees=%f but should be %f\n", lat2, lats[Nj-1]);
|
error(filename, msg_num, "latitudeOfLastGridPointInDegrees=%f but should be %f\n", lat2, lats[Nj-1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_reduced) {
|
if (is_reduced) {
|
||||||
|
@ -154,16 +175,16 @@ int process_file(const char* filename)
|
||||||
is_missing_Di = codes_is_missing(h, "iDirectionIncrement", &err);
|
is_missing_Di = codes_is_missing(h, "iDirectionIncrement", &err);
|
||||||
assert(err == CODES_SUCCESS);
|
assert(err == CODES_SUCCESS);
|
||||||
if (!is_missing_Ni) {
|
if (!is_missing_Ni) {
|
||||||
error("ERROR: For a reduced gaussian grid Ni should be missing\n");
|
error(filename, msg_num, "For a reduced gaussian grid Ni should be missing\n");
|
||||||
}
|
}
|
||||||
if (!is_missing_Di) {
|
if (!is_missing_Di) {
|
||||||
error("ERROR: For a reduced gaussian grid iDirectionIncrement should be missing\n");
|
error(filename, msg_num, "For a reduced gaussian grid iDirectionIncrement should be missing\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
CODES_CHECK(codes_get_size(h, "pl", &pl_len),0);
|
CODES_CHECK(codes_get_size(h, "pl", &pl_len),0);
|
||||||
assert(pl_len>0);
|
assert(pl_len>0);
|
||||||
if (pl_len != 2*N) {
|
if (pl_len != 2*N) {
|
||||||
error("ERROR: Length of pl array is %ld but should be 2*N (%ld)\n", pl_len, 2*N);
|
error(filename, msg_num, "Length of pl array is %ld but should be 2*N (%ld)\n", pl_len, 2*N);
|
||||||
}
|
}
|
||||||
pl = (long*)malloc(pl_len*sizeof(long));
|
pl = (long*)malloc(pl_len*sizeof(long));
|
||||||
assert(pl);
|
assert(pl);
|
||||||
|
@ -175,8 +196,8 @@ int process_file(const char* filename)
|
||||||
const long pl_start = pl[i];
|
const long pl_start = pl[i];
|
||||||
const long pl_end = pl[pl_len-1-i];
|
const long pl_end = pl[pl_len-1-i];
|
||||||
if ( pl_start != pl_end ) {
|
if ( pl_start != pl_end ) {
|
||||||
error("ERROR: pl array is not symmetric: pl[%ld]=%ld, pl[%ld]=%ld\n",
|
error(filename, msg_num, "pl array is not symmetric: pl[%ld]=%ld, pl[%ld]=%ld\n",
|
||||||
i, pl_start, pl_len-1-i, pl_end);
|
i, pl_start, pl_len-1-i, pl_end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,23 +207,23 @@ int process_file(const char* filename)
|
||||||
if (pl[i] > max_pl) max_pl = pl[i];
|
if (pl[i] > max_pl) max_pl = pl[i];
|
||||||
}
|
}
|
||||||
if (pl_sum != numberOfDataPoints) {
|
if (pl_sum != numberOfDataPoints) {
|
||||||
error("ERROR: Sum of pl array %ld does not match numberOfDataPoints %ld\n", pl_sum, numberOfDataPoints);
|
error(filename, msg_num, "Sum of pl array %ld does not match numberOfDataPoints %ld\n", pl_sum, numberOfDataPoints);
|
||||||
}
|
}
|
||||||
CODES_CHECK(codes_get_long(h,"isOctahedral",&is_octahedral),0);
|
CODES_CHECK(codes_get_long(h,"isOctahedral",&is_octahedral),0);
|
||||||
if (is_octahedral) {
|
if (is_octahedral) {
|
||||||
printf(" This is an Octahedral Gaussian grid\n");
|
if(verbose) printf(" This is an Octahedral Gaussian grid\n");
|
||||||
expected_lon2 = 360.0 - 360.0/max_pl;
|
expected_lon2 = 360.0 - 360.0/max_pl;
|
||||||
}
|
}
|
||||||
free(pl);
|
free(pl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fabs(lon2 - expected_lon2) > angular_tolerance) {
|
if (fabs(lon2 - expected_lon2) > angular_tolerance) {
|
||||||
error("ERROR: longitudeOfLastGridPointInDegrees=%f but should be %f\n", lon2, expected_lon2);
|
error(filename, msg_num, "longitudeOfLastGridPointInDegrees=%f but should be %f\n", lon2, expected_lon2);
|
||||||
}
|
}
|
||||||
|
|
||||||
CODES_CHECK(codes_get_size(h, "values", &sizeOfValuesArray),0);
|
CODES_CHECK(codes_get_size(h, "values", &sizeOfValuesArray),0);
|
||||||
if (sizeOfValuesArray != numberOfDataPoints) {
|
if (sizeOfValuesArray != numberOfDataPoints) {
|
||||||
error("ERROR: Number of data points %d different from size of values array %d\n",
|
error(filename, msg_num, "Number of data points %d different from size of values array %d\n",
|
||||||
numberOfDataPoints, sizeOfValuesArray);
|
numberOfDataPoints, sizeOfValuesArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,8 +231,8 @@ int process_file(const char* filename)
|
||||||
codes_handle_delete(h);
|
codes_handle_delete(h);
|
||||||
}
|
}
|
||||||
fclose(in);
|
fclose(in);
|
||||||
printf("\n");
|
if(verbose) printf("\n");
|
||||||
return 0;
|
return GRIB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
|
@ -233,20 +254,27 @@ int main(int argc, char** argv)
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* Process switches */
|
|
||||||
exit_on_error = 0;
|
exit_on_error = 0;
|
||||||
}
|
}
|
||||||
|
else if (STR_EQUAL(arg, "-v"))
|
||||||
|
{
|
||||||
|
if (argc < 3) {
|
||||||
|
usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
verbose = 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* We have a grib file */
|
/* We have a GRIB file */
|
||||||
process_file(arg);
|
process_file(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("###############\n");
|
if(verbose) printf("###############\n");
|
||||||
if (error_count == 0)
|
if (error_count == 0)
|
||||||
{
|
{
|
||||||
printf("ALL OK\n");
|
if(verbose) printf("ALL OK\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue