diff --git a/tools/Makefile.am b/tools/Makefile.am index a69c60d72..7bff97a8f 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -11,13 +11,18 @@ noinst_LTLIBRARIES = libgrib_tools.la libgrib_tools_la_SOURCES = grib_tools.c \ grib_options.c +bin_SCRIPTS = bufr_compare_dir bin_PROGRAMS = grib_keys grib_histogram grib_error grib_add big2gribex \ grib_debug grib_info grib_filter grib_ls grib_dump \ grib2ppm grib_set grib_get grib_get_data grib_copy grib_repair \ grib_packing grib_cmp grib_convert grib_distance grib_corruption_check\ grib_compare grib_list_keys parser grib_count grib_index_build grib1to2 \ - gg_sub_area_check grib_moments grib_to_netcdf grib_to_json + gg_sub_area_check grib_moments grib_to_netcdf grib_to_json \ + bufr_filter bufr_ls bufr_dump bufr_set bufr_get \ + bufr_copy bufr_compare bufr_index_build \ + taf_dump taf_ls taf_get taf_filter \ + metar_dump metar_ls metar_get metar_filter noinst_PROGRAMS = gaussian grib_diff mars_request xref all_keys #compile #dumpload grib_compare_old @@ -63,6 +68,25 @@ gaussian_SOURCES = gaussian.c gg_sub_area_check_SOURCES = gg_sub_area_check.c grib1to2_SOURCES = grib1to2.txt +bufr_filter_SOURCES = bufr_filter.c +bufr_ls_SOURCES = bufr_ls.c +bufr_dump_SOURCES = bufr_dump.c +bufr_set_SOURCES = bufr_set.c +bufr_get_SOURCES = bufr_get.c +bufr_copy_SOURCES = bufr_copy.c +bufr_compare_SOURCES = bufr_compare.c +bufr_index_build_SOURCES = bufr_index_build.c + +metar_dump_SOURCES = metar_dump.c +metar_ls_SOURCES = metar_ls.c +metar_get_SOURCES = metar_get.c +metar_filter_SOURCES = metar_filter.c + +taf_dump_SOURCES = taf_dump.c +taf_ls_SOURCES = taf_ls.c +taf_get_SOURCES = taf_get.c +taf_filter_SOURCES = taf_filter.c + INCLUDES = -I$(top_builddir)/src LDADD = libgrib_tools.la $(top_builddir)/src/libgrib_api.la diff --git a/tools/bufr_3to4.c b/tools/bufr_3to4.c new file mode 100644 index 000000000..0c6eb97ec --- /dev/null +++ b/tools/bufr_3to4.c @@ -0,0 +1,97 @@ +/* + * Copyright 2005-2014 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. + */ + +#include "ecCodes_internal.h" + +void usage(char* prog) { + printf("usage: %s infile outfile \n",prog); + exit(1); +} + + +int main(int argc,char* argv[]) { + + FILE* infh; + FILE* outfh; + char* filename; + char* ofilename; + void* mesg=NULL; + void* mesgo=NULL; + size_t size=0; + size_t osize=0; + off_t offset=0; + int write; + int err=0; + int error=0; + int count=0; + int edition=0; + grib_context* c=grib_context_get_default(); + + if (argc !=3) usage(argv[0]); + + n=0; + filename=argv[1]; + infh=fopen(filename,"r"); + if (!infh) { + perror(filename); + exit(1); + } + + ofilename=argv[1]; + outfh=fopen(ofilename,"w"); + if (!outfh) { + perror(ofilename); + exit(1); + } + + + count=0; + while ( (mesg=wmo_read_bufr_from_file_malloc ( infh,0, &size,&offset,&err))!=NULL ) { + if (err && err!=GRIB_END_OF_FILE) { + grib_context_log(c,GRIB_LOG_ERROR, + "unable to decode message: %s \n",grib_get_error_message(err)); + error=err; + } + edition=mesg[7]; + write=1; + switch (edition ) { + case 3: + omesg=grib_context_malloc_clear(c,size+4); + memcpy(omesg,mesg,7); + omesg[7]=4; + osize=8; + break; + case 4: + omesg=mesg; + break; + default : + error=1; + write=0; + grib_context_log(c,GRIB_LOG_ERROR, + "wrong edition %d, skipping message",edition); + } + if (write) { + if(fwrite(omesg,1,osize,outfh) != osize) { + perror(ofilename); + exit(1); + } + + } + if (mesg) {grib_context_free(c,mesg);mesg=NULL;} + if (omesg) {grib_context_free(c,omesg);omesg=NULL;} + count++; + } + + + fclose(infh); + fclose(outfh); + + return error; +} diff --git a/tools/bufr_compare.c b/tools/bufr_compare.c new file mode 100644 index 000000000..6e5067a76 --- /dev/null +++ b/tools/bufr_compare.c @@ -0,0 +1,1136 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: eccode_compare + * + * Author: Enrico Fucile + * + * + */ + +#include "grib_tools.h" + + +GRIB_INLINE static int grib_inline_strcmp(const char* a,const char* b) { + if (*a != *b) return 1; + while((*a!=0 && *b!=0) && *(a) == *(b) ) {a++;b++;} + return (*a==0 && *b==0) ? 0 : 1; +} + +GRIB_INLINE static int grib_inline_rstrcmp(const char* a,const char* b) { + char* p=(char*)a; + char* q=(char*)b; + while (*p != 0) p++; + while (*q != 0) q++; + q--;p--; + if (*q != *p) return 1; + while((p!=a && q!=b) && *(p) == *(q) ) {p--;q--;} + return (q==b) ? 0 : 1; +} + +typedef double (*compare_double_proc) (double*,double*,double*); + +typedef struct grib_error grib_error; +struct grib_error { + char* key; + int count; + grib_error* next; +}; + +grib_error* error_summary; + +compare_double_proc compare_double; +double global_tolerance=0; +int packingCompare=0; +grib_string_list* blacklist=0; +int compareAbsolute=1; + +static int compare_handles(grib_handle* h1,grib_handle* h2,grib_runtime_options* options); +static int compare_values(grib_runtime_options* options,grib_handle* h1,grib_handle *h2,const char *name,int type); +int error=0; +int count=0; +int lastPrint=0; +int force=0; +double maxAbsoluteError = 1e-19; +int onlyListed=1; +int headerMode=0; +int morein1=0; +int morein2=0; +int listFromCommandLine; +int verbose=0; +int tolerance_factor=1; +static int write_error=0; + +GRIB_INLINE static double compare_double_absolute(double *a,double *b,double *err) { + double ret=0; + double d=fabs(*a-*b); + if (d > *err) { + ret=d; + } + return ret; + /* return fabs(*a-*b) > *err ? fabs(*a-*b) : 0; */ +} + +static int write_count=0; + +static void write_message(grib_handle* h,const char* str) { + + const void *m; size_t s; + char fname[1024]={0,}; + FILE* fh=NULL; + int ioerr=0; + + grib_get_message(h,&m,&s); + sprintf(fname,"%s_%d.bufr",str,write_count); + + fh= fopen(fname,"w"); + if(!fh) { + ioerr=errno; + grib_context_log(h->context,(GRIB_LOG_ERROR)|(GRIB_LOG_PERROR), + "Error opening %s",fname); + exit(GRIB_IO_PROBLEM); + } + + if(fwrite(m,1,s,fh) != s) { + ioerr=errno; + grib_context_log(h->context,(GRIB_LOG_ERROR)|(GRIB_LOG_PERROR), + "Error writing to %s",fname); + exit(GRIB_IO_PROBLEM); + } + + fclose(fh); +} + +static void write_messages(grib_handle* h1,grib_handle* h2) { + if (!write_error) return; + write_count++; + + write_message(h1,"error1"); + write_message(h2,"error2"); +} + +static double compare_double_relative(double *a,double *b,double *err) { + double relativeError; + + if(fabs(*a) <= maxAbsoluteError || fabs(*b) <= maxAbsoluteError) + relativeError = fabs(*a-*b); + else if (fabs(*b) > fabs(*a)) + relativeError = fabs((*a-*b) / *b); + else + relativeError = fabs((*a-*b) / *a); + + return relativeError > *err ? relativeError : 0; +} + +static int blacklisted(const char* name) { + grib_string_list* b=blacklist; + while (b) { + if (!strcmp(name,b->value)) + return 1; + b=b->next; + } + return 0; +} + +static double relative_error(double a,double b,double err) { + double relativeError; + double maxAbsoluteError = 1e-19; + + if(fabs(a) <= maxAbsoluteError || fabs(b) <= maxAbsoluteError) + relativeError = fabs(a-b); + else if (fabs(b) > fabs(a)) + relativeError = fabs((a-b) / b); + else + relativeError = fabs((a-b) / a); + + return relativeError ; +} + + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value*/ + {"r",0,"Compare files in which the messages are not in the same order. This option is time expensive.\n",0,1,0}, + {"b:",0,0,0,1,0}, + {"d",0,"Write different messages on files\n",0,1,0}, + {"T:",0,0,1,0,"B"}, + {"c:",0,0,0,1,0}, + {"S:","start","First field to be processed.\n",0,1,0}, + {"E:","end","Last field to be processed.\n",0,1,0}, + {"a",0,"-c option modifier. The keys listed with the option -c will be added to the list of keys compared without -c.\n" + ,0,1,0}, + {"H",0,"Compare only message headers. Bit-by-bit compare on. Incompatible with -c option.\n",0,1,0}, + {"R:",0,0,0,1,0}, + {"A:",0,0,0,1,0}, + {"P",0,"Compare data values using the packing error as tolerance.\n",0,1,0}, + {"t:","factor","Compare data values using factor multiplied by the tolerance specified in options -P -R -A.\n",0,1,0}, + {"w:",0,0,0,1,0}, + {"f",0,0,0,1,0}, + {"F",0,0,1,0,0}, + {"q",0,0,1,0,0}, + {"M",0,0,1,0,0}, + {"I",0,0,1,0,0}, + {"V",0,0,0,1,0}, + {"7",0,0,0,1,0}, + {"v",0,0,0,1,0} +}; + +grib_handle* h1=NULL; +int counter=0; +int start=-1; +int end=-1; + +char* grib_tool_description= + "Compare grib messages contained in two files." + "\n\tIf some differences are found it fails returning an error code." + "\n\tFloating point values are compared exactly by default, different tolerance can be defined see -P -A -R." + "\n\tDefault behaviour: absolute error=0, bit-by-bit compare, same order in files."; + +char* grib_tool_name="bufr_compare"; +char* grib_tool_usage="[options] " + "file file"; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); + +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { + int ret=0,i; + int nfiles=1; + char orderby[]="md5Headers"; + grib_context* context=grib_context_get_default(); + + options->strict=1; + if (grib_options_on("S:")) + start=atoi(grib_options_get_option("S:")); + + if (grib_options_on("E:")) + end=atoi(grib_options_get_option("E:")); + + if (grib_options_on("f")) force=1; + else force=0; + + if (grib_options_on("d")) write_error=1; + else write_error=0; + + verbose = grib_options_on("v"); + + listFromCommandLine=0; + if (grib_options_on("c:") || grib_options_on("e")) + listFromCommandLine=1; + + if (grib_options_on("a")) onlyListed=0; + else onlyListed=1; + + if (grib_options_on("H")) headerMode=1; + else headerMode=0; + + if (grib_options_on("H") && grib_options_on("c:")) { + printf("Error: -H and -c options are incompatible. Choose one of the two please.\n"); + exit(1); + } + if (grib_options_on("a") && !grib_options_on("c:")) { + printf("Error: -a option requires -c option. Please define a list of keys with the -c option.\n"); + exit(1); + } + + if (grib_options_on("b:")) { + grib_string_list *next=0; + int i=0; + blacklist=grib_context_malloc_clear(context,sizeof(grib_string_list)); + blacklist->value=grib_context_strdup(context,options->set_values[0].name); + next=blacklist; + for (i=1;iset_values_count;i++) { + next->next=grib_context_malloc_clear(context,sizeof(grib_string_list)); + next->next->value=grib_context_strdup(context,options->set_values[i].name); + next=next->next; + } + context->blacklist=blacklist; + } + + if (grib_options_on("r")) { + char* filename[1]; + filename[0]=options->infile_extra->name; + options->random=1; + options->orderby=strdup(orderby); + options->idx=grib_fieldset_new_from_files(context,filename, + nfiles,0,0,0,orderby,&ret); + if (ret) { + printf("unable to create index for input file %s (%s)", + options->infile_extra->name,grib_get_error_message(ret)); + exit(ret); + } + } else { + options->random=0; + options->infile_extra->file=fopen(options->infile_extra->name,"r"); + + if (!options->infile_extra->file) { + perror(options->infile_extra->name); + exit(1); + } + } + + global_tolerance=0; + compare_double= &compare_double_absolute; + if (grib_options_on("R:")) { + global_tolerance=0; + for (i=0;itolerance_count;i++) { + if (!strcmp((options->tolerance[i]).name,"all")) { + global_tolerance=(options->tolerance[i]).double_value; + break; + } + if (!strcmp((options->tolerance[i]).name,"global")) { + global_tolerance=(options->tolerance[i]).double_value; + break; + } + } + compare_double= &compare_double_relative; + compareAbsolute=0; + } + if (grib_options_on("A:")){ + if (grib_options_on("R:")) { + maxAbsoluteError = atof(grib_options_get_option("A:")); + } else { + compare_double= &compare_double_absolute; + global_tolerance = atof(grib_options_get_option("A:")); + } + } + if (grib_options_on("P")) { + packingCompare=1; + compare_double= &compare_double_absolute; + } + + if (grib_options_on("t:")) + tolerance_factor=atof(grib_options_get_option("t:")); + + + return 0; +} + +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; +} +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +static void printInfo(grib_handle* h) { + + printf("== %d == DIFFERENCE == ",count); + lastPrint=count; + +} + +static void print_index_key_values(grib_index* index,int counter,const char* error_message) { + grib_index_key* keys=index->keys; + printf("== %d == ",counter); + if (error_message) printf("%s == ",error_message); + while (keys) { + printf("%s=%s ",keys->name,keys->value); + keys=keys->next; + } + printf("\n"); +} + +static grib_handle* grib_handle_new_from_file_x(grib_context* c,FILE* f,int +mode,int headers_only,int *err) { + return eccode_bufr_new_from_file(c,f,headers_only,err); +} + +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + int err=0; + count++; + + if (options->through_index) { + grib_index* idx1=options->index1; + verbose=0; + counter++; + + if ( start>0 && counter < start ) return 0; + if ( end>0 && counter > end ) { + options->stop=1; + return 0; + } + + grib_index_search_same(idx1,h); + h1=codes_new_from_index(idx1,CODES_BUFR,&err); + if (options->verbose) { + off_t offset=0; + char* filename=grib_get_field_file(options->index2,&offset); + printf("file1=\"%s\" ",filename); + filename=grib_get_field_file(options->index1,&offset); + printf("file2=\"%s\" \n",filename); + print_index_key_values(options->index1,counter,NULL); + } + + if (!h1) { + if (!options->verbose) + print_index_key_values(idx1,counter,"NOT FOUND "); + } + + if (!h1 || err!= GRIB_SUCCESS ) { + morein1++; + if (h1) grib_handle_delete(h1); + return 0; + } + + if(compare_handles(h,h1,options)) { + error++; + if (!force) exit(1); + } + + grib_handle_delete(h1); + + return 0; + + } else if (options->random) + h1 = grib_fieldset_next_handle(options->idx,&err); + else + h1=grib_handle_new_from_file_x(h->context,options->infile_extra->file,options->mode,0,&err); + + if (!h1 || err!= GRIB_SUCCESS ) { + morein2++; + if (h1) grib_handle_delete(h1); + return 0; + } + + if(compare_handles(h1,h,options)) { + error++; + if (!force) exit(1); + } + + grib_handle_delete(h1); + + return 0; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + int err=0; + if (!options->through_index && !options->random) { + h1=grib_handle_new_from_file(h->context,options->infile_extra->file,&err); + + if (!h1 || err!= GRIB_SUCCESS) + morein2++; + + grib_handle_delete(h1); + + + } + + grib_handle_delete(h); + count++; + + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +int grib_tool_finalise_action(grib_runtime_options* options) { + grib_error* e=error_summary; + int err=0; + grib_context* c=grib_context_get_default(); + error+=morein1+morein2; + + /*if (grib_options_on("w:")) return 0;*/ + + if (error) { + printf("\n## ERRORS SUMMARY #######\n"); + } + while ((h1=grib_handle_new_from_file(c,options->infile_extra->file,&err))) { + morein1++; + if (h1) grib_handle_delete(h1); + } + if (morein1>0) { + printf("##\n## Different number of messages \n"); + printf("## %d more messages in %s than in %s\n",morein1, + options->infile_extra->name,options->infile->name); + } + + if (morein2>0) { + printf("##\n## Different number of messages \n"); + printf("## %d more messages in %s than in %s\n",morein2, + options->infile->name,options->infile_extra->name); + } + + if (error) { + printf("##\n## Summary of different key values \n"); + while (e) { + printf ("## %s ( %d different )\n",e->key,e->count); + e=e->next; + } + + printf("##\n## %d different messages out of %d\n\n",error,count); + } + if (options->through_index) { + grib_index_delete(options->index1); + grib_index_delete(options->index2); + } + + + if (error !=0) exit(1); + return 0; +} + +static void save_error(grib_context* c,const char* key) { + grib_error* e=0; + grib_error* next=0; + int saved=0; + + if (!error_summary) { + error_summary=grib_context_malloc_clear(c,sizeof(grib_error)); + error_summary->count=1; + error_summary->key=grib_context_strdup(c,key); + return; + } + + e=error_summary; + next=e; + + while (next) { + if (!strcmp(next->key,key)) { + next->count++; + saved=1; + break; + } + e=next; + next=next->next; + } + + if (!saved) { + e->next=grib_context_malloc_clear(c,sizeof(grib_error)); + e->next->count=1; + e->next->key=grib_context_strdup(c,key); + } + + +} + +static int compare_values(grib_runtime_options* options,grib_handle* h1,grib_handle *h2,const char *name,int type) { + size_t len1 = 0; + size_t len2 = 0; + int err=0,i=0; + int err1; + int err2; + int type1,type2; + int countdiff; + int isangle=0; + int isMissing1,isMissing2; + + char *sval1 = NULL,*sval2 = NULL; + unsigned char *uval1 = NULL,*uval2 = NULL; + double *dval1 = NULL, *dval2 = NULL; + long *lval1 = NULL, *lval2 = NULL; + int failed=0; + double maxdiff=0; + double packingError1,packingError2; + double value_tolerance=0; + grib_context* c=h1->context; + + + type1=type; + type2=type; + if (verbose) printf(" comparing %s",name); + + if( type1==GRIB_TYPE_UNDEFINED && (err = grib_get_native_type(h1,name,&type1)) != GRIB_SUCCESS) + { + printInfo(h1); + printf("Oops... cannot get type of [%s] in 1st field: %s\n",name,grib_get_error_message(err)); + save_error(c,name); + return err; + } + + if(type2==GRIB_TYPE_UNDEFINED && (err = grib_get_native_type(h2,name,&type2)) != GRIB_SUCCESS) + { + if(err == GRIB_NOT_FOUND) + { + printInfo(h1); + printf("[%s] not found in 2nd field\n",name); + save_error(c,name); + return err; + } + printInfo(h1); + printf("Oops... cannot get type of [%s] in 2nd field: %s\n",name,grib_get_error_message(err)); + save_error(c,name); + return err; + } + + /* + if(type1 != type2) + { + printInfo(h1); + printf("Warning, [%s] has different types: 1st field: [%s], 2nd field: [%s]\n", + name,grib_get_type_name(type1),grib_get_type_name(type2)); + return GRIB_TYPE_MISMATCH; + } + */ + + if(type1 == GRIB_TYPE_LABEL) + return err; + + if(type1 == GRIB_TYPE_SECTION) + return err; + + + if((err = grib_get_size(h1,name,&len1)) != GRIB_SUCCESS) + { + printInfo(h1); + printf("Oops... cannot get size of [%s] in 1st field: %s\n",name,grib_get_error_message(err)); + save_error(c,name); + return err; + } + + if((err = grib_get_size(h2,name,&len2)) != GRIB_SUCCESS) + { + if(err == GRIB_NOT_FOUND) + { + printInfo(h1); + printf("[%s] not found in 2nd field\n",name); + save_error(c,name); + return err; + } + + printInfo(h1); + printf("Oops... cannot get size of [%s] in 2nd field: %s\n",name,grib_get_error_message(err)); + save_error(c,name); + return err; + } + + /* + if(len1 != len2 && type1 != GRIB_TYPE_STRING) + { + printInfo(h1); + printf("[%s] has different size: 1st field: %ld, 2nd field: %ld\n",name,(long)len1,(long)len2); + save_error(c,name); + return GRIB_COUNT_MISMATCH; + } + */ + + isMissing1= ( (grib_is_missing(h1,name,&err1)==1) && (err1 == 0) ) ? 1 : 0; + isMissing2= ( (grib_is_missing(h2,name,&err2)==1) && (err2 == 0) ) ? 1 : 0; + + if ((isMissing1==1) && (isMissing2==1)) { + if (verbose) printf(" is set to missing in both fields\n"); + return GRIB_SUCCESS; + } + + if (isMissing1==1) { + if (verbose) printf(" is set to missing in 1st field\n"); + printInfo(h1); + printf("%s is set to missing in 1st field is not missing in 2nd field\n",name); + err1 = GRIB_VALUE_MISMATCH; + save_error(c,name); + return GRIB_VALUE_MISMATCH; + } + + if (isMissing2==1) { + if (verbose) printf(" is set to missing in 1st field\n"); + printInfo(h1); + printf("%s is set to missing in 2nd field is not missing in 1st field\n",name); + err1 = GRIB_VALUE_MISMATCH; + save_error(c,name); + return GRIB_VALUE_MISMATCH; + } + + switch(type1) + { + case GRIB_TYPE_STRING: + if (verbose) printf(" as string\n"); + grib_get_string_length(h1,name,&len1); + grib_get_string_length(h2,name,&len2); + sval1 = grib_context_malloc(h1->context,len1*sizeof(char)); + sval2 = grib_context_malloc(h2->context,len2*sizeof(char)); + + if((err1 = grib_get_string(h1,name,sval1,&len1)) != GRIB_SUCCESS) + { + printInfo(h1); + printf("Oops... cannot get string value of [%s] in 1st field: %s\n", + name,grib_get_error_message(err1)); + save_error(c,name); + } + + if((err2 = grib_get_string(h2,name,sval2,&len2)) != GRIB_SUCCESS) + { + printInfo(h1); + printf("Oops... cannot get string value of [%s] in 2nd field: %s\n", + name,grib_get_error_message(err2)); + save_error(c,name); + } + + if(err1 == GRIB_SUCCESS && err2 == GRIB_SUCCESS) + { + if(grib_inline_strcmp(sval1,sval2) != 0) + { + printInfo(h1); + printf("string [%s]: [%s] != [%s]\n", + name,sval1,sval2); + err1 = GRIB_VALUE_MISMATCH; + save_error(c,name); + } + } + + grib_context_free(h1->context,sval1); + grib_context_free(h2->context,sval2); + + if(err1) return err1; + if(err2) return err2; + + break; + + case GRIB_TYPE_LONG: + if (verbose) printf(" as long\n"); + + lval1 = grib_context_malloc(h1->context,len1*sizeof(long)); + lval2 = grib_context_malloc(h2->context,len2*sizeof(long)); + + if((err1 = grib_get_long_array(h1,name,lval1,&len1)) != GRIB_SUCCESS) + { + printInfo(h1); + printf("Oops... cannot get long value of [%s] in 1st field: %s\n", + name,grib_get_error_message(err1)); + save_error(c,name); + } + + if((err2 = grib_get_long_array(h2,name,lval2,&len2)) != GRIB_SUCCESS) + { + printInfo(h1); + printf("Oops... cannot get long value of [%s] in 2nd field: %s\n", + name,grib_get_error_message(err2)); + save_error(c,name); + } + + + if(err1 == GRIB_SUCCESS && err2 == GRIB_SUCCESS) + { + int i; + countdiff=0; + for(i = 0; i < len1; i++) + if(lval1[i] != lval2[i]) countdiff++; + + if (countdiff) { + printInfo(h1); + save_error(c,name); + err1 = GRIB_VALUE_MISMATCH; + if(len1 == 1) + printf("long [%s]: [%ld] != [%ld]\n", + name,*lval1,*lval2); + else + printf("long [%s] %d out of %ld different\n", + name,countdiff,(long)len1); + } + } + + + grib_context_free(h1->context,lval1); + grib_context_free(h2->context,lval2); + + if(err1) return err1; + if(err2) return err2; + break; + + case GRIB_TYPE_DOUBLE: + if (verbose) printf(" as double"); + dval1 = grib_context_malloc(h1->context,len1*sizeof(double)); + dval2 = grib_context_malloc(h2->context,len2*sizeof(double)); + + isangle=0; + value_tolerance=global_tolerance; + if (!grib_inline_strcmp(name,"packedValues") || !grib_inline_strcmp(name,"values") + || !grib_inline_strcmp(name,"codedValues")) { + packingError1=0; + packingError2=0; + err1=grib_get_double(h1,"packingError",&packingError1); + err2=grib_get_double(h2,"packingError",&packingError2); + if (packingCompare) + value_tolerance = packingError1 > packingError2 ? packingError1 : packingError2; + } else if (!grib_inline_strcmp(name,"unpackedValues") ) { + packingError1=0; + packingError2=0; + err1=grib_get_double(h1,"unpackedError",&packingError1); + err2=grib_get_double(h2,"unpackedError",&packingError2); + if (packingCompare) + value_tolerance = packingError1 > packingError2 ? packingError1 : packingError2; + } else if ( !grib_inline_rstrcmp(name,"InDegrees")) { + packingError1=0.0005; + packingError2=0.0005; + isangle=1; + value_tolerance = packingError1 > packingError2 ? packingError1 : packingError2; + } else if (!grib_inline_strcmp(name,"referenceValue") ) { + packingError1=0; + packingError2=0; + err1=grib_get_double(h1,"referenceValueError",&packingError1); + err2=grib_get_double(h2,"referenceValueError",&packingError2); + value_tolerance = packingError1 > packingError2 ? packingError1 : packingError2; + } + + if (!compareAbsolute) { + for (i=0;itolerance_count;i++) { + if (!strcmp((options->tolerance[i]).name,name)) { + value_tolerance=(options->tolerance[i]).double_value; + break; + } + } + } + + if((err1 = grib_get_double_array(h1,name,dval1,&len1)) != GRIB_SUCCESS) + { + printInfo(h1); + printf("Oops... cannot get double value of [%s] in 1st field: %s\n", + name,grib_get_error_message(err1)); + save_error(c,name); + } + + if((err2 = grib_get_double_array(h2,name,dval2,&len2)) != GRIB_SUCCESS) + { + printInfo(h1); + printf("Oops... cannot get double value of [%s] in 2nd field: %s\n", + name,grib_get_error_message(err2)); + save_error(c,name); + } + + if(err1 == GRIB_SUCCESS && err2 == GRIB_SUCCESS && len1!=len2) + { + printInfo(h1); + printf("Different size for \"%s\" [%ld] [%ld]\n",name,(long)len1,(long)len2); + save_error(c,name); + } + if(err1 == GRIB_SUCCESS && err2 == GRIB_SUCCESS && len1==len2) + { + int i,imaxdiff; + double diff; + double *pv1,*pv2,dnew1,dnew2; + maxdiff=0; + imaxdiff=0; + countdiff=0; + pv1=dval1; + pv2=dval2; + if (isangle) { + dnew1=*dval1; dnew2=*dval2; + pv1=&dnew1; pv2=&dnew2; + if (*dval1 < 0 ) dnew1 += 360.0 ; + if (*dval2 < 0 ) dnew2 += 360.0 ; + if (*dval1 > 360 ) dnew1 -= 360.0 ; + if (*dval2 > 360 ) dnew2 -= 360.0 ; + } + value_tolerance*=tolerance_factor; + if (verbose) printf(" (%d values) tolerance=%g\n",(int)len1,value_tolerance); + for(i = 0; i < len1; i++) { + if((diff=compare_double(pv1++,pv2++,&value_tolerance))!=0) { + failed=1; + countdiff++; + if (maxdiff < diff) {maxdiff=diff;imaxdiff=i;} + err1 = GRIB_VALUE_MISMATCH; + } + } + + if (countdiff) { + printInfo(h1); + save_error(c,name); + if (len1>1) { + printf("double [%s]: %d out of %ld different\n",name,countdiff,(long)len1); + if (compareAbsolute) printf(" max"); + printf(" absolute diff. = %.16e,",fabs(dval1[imaxdiff]-dval2[imaxdiff])); + if (!compareAbsolute) printf(" max"); + printf(" relative diff. = %g",relative_error(dval1[imaxdiff],dval2[imaxdiff],value_tolerance)); + printf("\n\tmax diff. element %d: %.20e %.20e", + imaxdiff,dval1[imaxdiff],dval2[imaxdiff]); + printf("\n\ttolerance=%.16e",value_tolerance); + if (packingError2!=0 || packingError1!=0) + printf(" packingError: [%g] [%g]",packingError1,packingError2); + + if (!grib_inline_strcmp(name,"packedValues") || !grib_inline_strcmp(name,"values") + || !grib_inline_strcmp(name,"codedValues")) { + double max1,min1,max2,min2; + grib_get_double(h1,"max",&max1); + grib_get_double(h1,"min",&min1); + grib_get_double(h2,"max",&max2); + grib_get_double(h2,"min",&min2); + printf("\n\tvalues max= [%g] [%g] min= [%g] [%g]",max1,max2,min1,min2); + } + printf("\n"); + } else { + printf("double [%s]: [%.20e] != [%.20e]\n", + name,dval1[0],dval2[0]); + printf("\tabsolute diff. = %g,",fabs(dval1[0]-dval2[0])); + printf(" relative diff. = %g\n",relative_error(dval1[0],dval2[0],value_tolerance)); + printf("\ttolerance=%g\n",value_tolerance); + } + } + } + + grib_context_free(h1->context,dval1); + grib_context_free(h2->context,dval2); + + if(err1) return err1; + if(err2) return err2; + break; + + case GRIB_TYPE_BYTES: + if (verbose) printf(" as bytes\n"); + if (options->mode==MODE_BUFR) return 0; + if (len1==0) len1=512; + if (len2==0) len2=512; + uval1 = grib_context_malloc(h1->context,len1*sizeof(unsigned char)); + uval2 = grib_context_malloc(h2->context,len2*sizeof(unsigned char)); + + if((err1 = grib_get_bytes(h1,name,uval1,&len1)) != GRIB_SUCCESS) + { + printInfo(h1); + save_error(c,name); + printf("Oops... cannot get bytes value of [%s] in 1st field: %s\n", + name,grib_get_error_message(err1)); + } + + if((err2 = grib_get_bytes(h2,name,uval2,&len2)) != GRIB_SUCCESS) + { + printInfo(h1); + save_error(c,name); + printf("Oops... cannot get bytes value of [%s] in 2nd field: %s\n", + name,grib_get_error_message(err2)); + } + + if(err1 == GRIB_SUCCESS && err2 == GRIB_SUCCESS) + { + if(memcmp(uval1,uval2,len1) != 0) + { + int i; + for(i = 0; i < len1; i++) + if(uval1[i] != uval2[i]) + { + printInfo(h1); + save_error(c,name); + if(len1 == 1) + printf("[%s] byte values are different: [%02x] and [%02x]\n", + name,uval1[i],uval2[i]); + else + printf("[%s] byte value %d of %ld are different: [%02x] and [%02x]\n", + name,i,(long)len1,uval1[i],uval2[i]); + + err1 = GRIB_VALUE_MISMATCH; + break; + } + err1 = GRIB_VALUE_MISMATCH; + } + } + + grib_context_free(h1->context,uval1); + grib_context_free(h2->context,uval2); + + if(err1) return err1; + if(err2) return err2; + break; + + case GRIB_TYPE_LABEL: + if (verbose) printf(" as label\n"); + break; + + default: + if (verbose) printf("\n"); + printInfo(h1); + save_error(c,name); + printf("Cannot compare [%s], unsupported type %d\n",name,type1); + return GRIB_UNABLE_TO_COMPARE_ACCESSORS; + break; + } + + return GRIB_SUCCESS; + +} + +static int compare_all_dump_keys(grib_handle* h1,grib_handle* h2,grib_runtime_options* options,int *err) { + int ret=0; + const char* name=NULL; + grib_keys_iterator* iter = NULL; + grib_set_long(h1,"unpack",1); + grib_set_long(h2,"unpack",1); + iter=grib_keys_iterator_new(h1,0,NULL); + + if (!iter) { + printf("ERROR: unable to get iterator\n"); + exit(1); + } + + while(grib_keys_iterator_next(iter)) + { + grib_accessor* xa=grib_keys_iterator_get_accessor(iter); + name=grib_keys_iterator_get_name(iter); + /*printf("----- comparing %s\n",name);*/ + + if (blacklisted(name)) continue; + if (xa==NULL || ( xa->flags & GRIB_ACCESSOR_FLAG_DUMP )==0 ) continue; + if(compare_values(options,h1,h2,name,GRIB_TYPE_UNDEFINED)) { + err++; + write_messages(h1,h2); + ret=1; + } + } + + grib_keys_iterator_delete(iter); + return ret; +} + +static int compare_handles(grib_handle* h1,grib_handle* h2,grib_runtime_options* options) +{ + int err = 0; + int i=0; + grib_keys_iterator* iter = NULL; + const char* name=NULL; + + /* mask only if no -c option or headerMode (-H)*/ + if (blacklist && ( !listFromCommandLine || headerMode )) { + grib_string_list* nextb=blacklist; + while (nextb) { + grib_clear(h1,nextb->value); + grib_clear(h2,nextb->value); + nextb=nextb->next; + } + } + + if (headerMode) { + const void *msg1=NULL,*msg2=NULL; + size_t size1=0,size2=0; + grib_handle *h11, *h22; + GRIB_CHECK_NOLINE(grib_get_message_headers(h1,&msg1,&size1),0); + GRIB_CHECK_NOLINE(grib_get_message_headers(h2,&msg2,&size2),0); + if (size1==size2 && !memcmp(msg1,msg2,size1)) + return 0; + + err=0; + h11=grib_handle_new_from_partial_message(h1->context,(void*)msg1,size1); + h22=grib_handle_new_from_partial_message(h1->context,(void*)msg2,size2); + + iter=grib_keys_iterator_new(h11, + GRIB_KEYS_ITERATOR_SKIP_COMPUTED,NULL); + + if (!iter) { + printf("ERROR: unable to get iterator\n"); + exit(1); + } + + while(grib_keys_iterator_next(iter)) + { + name=grib_keys_iterator_get_name(iter); + /*printf("----- comparing %s\n",name);*/ + + if (blacklisted(name)) continue; + if(compare_values(options,h11,h22,name,GRIB_TYPE_UNDEFINED)) { + err++; + write_messages(h11,h22); + } + } + + grib_keys_iterator_delete(iter); + grib_handle_delete(h11); + grib_handle_delete(h22); + return err; + } + + if ( listFromCommandLine && onlyListed ) { + for (i=0; i< options->compare_count; i++) { + if (blacklisted((char*)options->compare[i].name)) continue; + if (options->compare[i].type == GRIB_NAMESPACE) { + iter=grib_keys_iterator_new(h1,0,(char*)options->compare[i].name); + if (!iter) { + printf("ERROR: unable to get iterator\n"); + exit(1); + } + while(grib_keys_iterator_next(iter)) + { + name=grib_keys_iterator_get_name(iter); + /*printf("----- comparing %s\n",name);*/ + + if (blacklisted(name)) continue; + if(compare_values(options,h1,h2,name,GRIB_TYPE_UNDEFINED)) { + err++; + write_messages(h1,h2); + } + } + grib_keys_iterator_delete(iter); + } else { + if( compare_values(options,h1,h2,options->compare[i].name,options->compare[i].type)) + err++; + write_messages(h1,h2); + } + } + } else { + const void *msg1=NULL,*msg2=NULL; + size_t size1=0,size2=0; + int memcmp_ret=0; + /* int ii=0; */ + GRIB_CHECK_NOLINE(grib_get_message(h1,&msg1,&size1),0); + GRIB_CHECK_NOLINE(grib_get_message(h2,&msg2,&size2),0); + if (size1==size2 && !(memcmp_ret=memcmp(msg1,msg2,size1))) { + return 0; + } +#if 0 + else if (options->mode == MODE_BUFR ) { + int lcount=count; + if (options->current_infile) lcount=options->current_infile->filter_handle_count; + if (size1 != size2) { + printf("#%d different size: %d!=%d\n",lcount,(int)size1,(int)size2); + } + if (memcmp_ret) { + unsigned char *m1=(unsigned char*)msg1; + unsigned char *m2=(unsigned char*)msg2; + printf("=== list of different bytes for message %d\n",lcount); + for (ii=0;iicompare_count; i++) { + if (blacklisted(name)) continue; + if (options->compare[i].type == GRIB_NAMESPACE) { + iter=grib_keys_iterator_new(h1,0,(char*)options->compare[i].name); + if (!iter) { + printf("ERROR: unable to get iterator for %s\n",options->compare[i].name ); + exit(1); + } + while(grib_keys_iterator_next(iter)) + { + name=grib_keys_iterator_get_name(iter); + /*printf("----- comparing %s\n",name);*/ + + if (blacklisted(name)) continue; + if(compare_values(options,h1,h2,name,GRIB_TYPE_UNDEFINED)) { + err++; + write_messages(h1,h2); + compare_all_dump_keys(h1,h2,options,&err); + } + } + grib_keys_iterator_delete(iter); + } else { + if( compare_values(options,h1,h2,options->compare[i].name,options->compare[i].type)) { + err++; + write_messages(h1,h2); + compare_all_dump_keys(h1,h2,options,&err); + } + } + } + } else { + compare_all_dump_keys(h1,h2,options,&err); + } + + } + return err; +} diff --git a/tools/bufr_compare_dir b/tools/bufr_compare_dir new file mode 100755 index 000000000..9672c763b --- /dev/null +++ b/tools/bufr_compare_dir @@ -0,0 +1,30 @@ +#!/bin/ksh + +keys="md5Structure,md5Data,typicalDate,typicalTime,rdbType,rdbSubtype,ident,satelliteID,localLatitude,localLongitude,localLatitude1,localLongitude1,localLatitude2,localLongitude2" + +opt="" + +if [[ $# -eq 3 ]] +then + opt=$1 + dir1=$2 + dir2=$3 +fi + +if [[ $# -eq 2 ]] +then + dir1=$1 + dir2=$2 +fi + +if [[ $# -gt 3 ]] || [[ $# -lt 2 ]] +then + echo usage: [bufr_compare options] bufr_compare_dir directory1 directory2 + exit 1 +fi + +bufr_index_build -k $keys -o 1.idx $dir1/* > /dev/null +bufr_index_build -k $keys -o 2.idx $dir2/* > /dev/null + +bufr_compare -f $opt 1.idx 2.idx +rm -f 1.idx 2.idx diff --git a/tools/bufr_copy.c b/tools/bufr_copy.c new file mode 100644 index 000000000..10e39fc9d --- /dev/null +++ b/tools/bufr_copy.c @@ -0,0 +1,117 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_copy + * + * Author: Enrico Fucile + * + * + */ + +#include "grib_tools.h" + +char* grib_tool_description="Copies the content of grib files printing" + " values of some keys."; +char* grib_tool_name="bufr_copy"; +char* grib_tool_usage="[options] file file ... output_file"; + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value */ + {"f",0,0,0,1,0}, + {"c",0,0,1,0,0}, + {"r",0,0,0,1,0}, + {"q",0,0,1,0,0}, + {"p:",0,0,1,1,0}, + {"s:",0,0,0,1,0}, + {"P:",0,0,0,1,0}, + {"w:","key[:{s/d/l}]=value,key[:{s/d/l}]=value,...","\n\t\tWhere clause." + "\n\t\tOnly grib messages matching the key/value constraints are " + "copied to the\n\t\toutput_grib_file.\n\t\tFor each key a string (key:s) or a " + "double (key:d) or a long (key:l)\n\t\ttype can be defined. Default type " + "is string.\n",0,1,0}, + {"B:",0,0,0,1,0}, + {"V",0,0,0,1,0}, + {"W:",0,0,0,1,0}, + {"M",0,0,0,1,0}, + {"U",0,0,1,0,0}, + {"H",0,0,1,0,0}, + {"T:",0,0,1,0,"B"}, + {"S",0,0,1,0,0}, + {"g",0,0,0,1,0}, + {"G",0,0,0,1,0}, + {"7",0,0,0,1,0}, + {"v",0,0,0,1,0} +}; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); + +int main(int argc, char *argv[]) { + int ret=grib_tool(argc,argv); + return ret; +} + +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { +#if 0 + if (options->outfile && options->outfile->name) { + options->outfile->file = fopen(options->outfile->name,"w"); + if(!options->outfile->file) { + perror(options->outfile->name); + exit(1); + } + } +#endif + return 0; +} + + +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; +} + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + int err=0; + if (!options->skip) { + + if (options->set_values_count != 0) + err=grib_set_values(h,options->set_values,options->set_values_count); + + if( err != GRIB_SUCCESS && options->fail) exit(err); + } + + grib_tools_write_message(options,h); + return 0; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +int grib_tool_finalise_action(grib_runtime_options* options) { +/* + if (options->outfile->file) { + fclose(options->outfile->file); + } +*/ + return 0; +} diff --git a/tools/bufr_dump.c b/tools/bufr_dump.c new file mode 100644 index 000000000..c4bc4d394 --- /dev/null +++ b/tools/bufr_dump.c @@ -0,0 +1,170 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_dump + * + * Author: Enrico Fucile + * + * + */ + +#include "grib_tools.h" + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value*/ + {"j",0,0,0,1,0}, + {"S",0,0,1,0,0}, + {"O",0,"Octet mode. WMO documentation style dump.\n",0,1,0}, + {"D",0,0,0,1,0}, + {"d",0,"Print all data values.\n",1,1,0}, + {"u",0,"Print only some values.\n",0,1,0}, + {"C",0,0,0,1,0}, + {"t",0,0,0,1,0}, + {"H",0,0,0,1,0}, + {"a",0,0,0,1,0}, + {"w:",0,0,0,1,0}, + {"M",0,0,0,1,0}, + {"T:",0,0,1,0,"B"}, + {"7",0,0,0,1,0}, + {"V",0,0,0,1,0}, + {"q",0,0,1,0,0}, + {"x",0,0,0,1,0} +}; + +char* grib_tool_description="Dump the content of a grib file in different formats."; +char* grib_tool_name="bufr_dump"; +char* grib_tool_usage="[options] file file ..."; +static int json=0; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); + +/** +*grib_dump +*Dump the content of a grib file +* +*/ +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { + + int opt=grib_options_on("C")+grib_options_on("O")+grib_options_on("D"); + + options->dump_mode = "default"; + + + if (opt > 1) { + printf("%s: simultaneous j/C/O/D options not allowed\n",grib_tool_name); + exit(1); + } + + if (grib_options_on("j")) { + options->dump_mode = "json"; + json=1; + } + + if (grib_options_on("C")) { + options->dump_mode = "c_code"; + if (grib_options_on("d")) + options->dump_flags = 0; + else + options->dump_flags = GRIB_DUMP_FLAG_NO_DATA; + } + + if (grib_options_on("O")) { + options->dump_mode = "wmo"; + options->dump_flags = GRIB_DUMP_FLAG_CODED + | GRIB_DUMP_FLAG_OCTECT + | GRIB_DUMP_FLAG_VALUES + | GRIB_DUMP_FLAG_READ_ONLY; + } + + if (grib_options_on("D")) { + options->dump_mode = "debug"; + options->dump_flags = GRIB_DUMP_FLAG_VALUES + | GRIB_DUMP_FLAG_READ_ONLY; + } + + if (grib_options_on("a")) + options->dump_flags |= GRIB_DUMP_FLAG_ALIASES; + + if (grib_options_on("t")) + options->dump_flags |= GRIB_DUMP_FLAG_TYPE; + + if (grib_options_on("H")) + options->dump_flags |= GRIB_DUMP_FLAG_HEXADECIMAL; + + if (grib_options_on("d") && !grib_options_on("u")) + options->dump_flags |= GRIB_DUMP_FLAG_ALL_DATA; + + return 0; +} + +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; +} + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + char tmp[1024]; + if (!options->current_infile->name) return 0; + if (json) return 0; + + sprintf(tmp,"FILE: %s ",options->current_infile->name); + if (!grib_options_on("C")) + fprintf(stdout,"***** %s\n",tmp); + return 0; +} + +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + long length=0; + char tmp[1024]; + char identifier[100]; + size_t idlen=100; + int i; + if (grib_get_long(h,"totalLength",&length) != GRIB_SUCCESS) + length=-9999; + + for (i=0;iprint_keys_count;i++) + grib_set_flag(h,options->print_keys[i].name,GRIB_ACCESSOR_FLAG_DUMP); + + if (json) { + } else { + sprintf(tmp,"MESSAGE %d ( length=%ld )",options->handle_count,length); + if (!grib_options_on("C")) + fprintf(stdout,"#============== %-38s ==============\n",tmp); + if (!strcmp(options->dump_mode,"default")) { + GRIB_CHECK_NOLINE(grib_get_string(h,"identifier",identifier,&idlen),0); + printf("%s {\n",identifier); + } + } + + grib_dump_content(h,stdout,options->dump_mode,options->dump_flags,0); + + if (!strcmp(options->dump_mode,"default")) + printf("}\n"); + return 0; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +int grib_tool_finalise_action(grib_runtime_options* options) { + return 0; +} diff --git a/tools/bufr_filter.c b/tools/bufr_filter.c new file mode 100644 index 000000000..b8b38fe47 --- /dev/null +++ b/tools/bufr_filter.c @@ -0,0 +1,102 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_filter + * + * Author: Enrico Fucile + * + * + */ + +#include "grib_tools.h" + + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value */ + {"f",0,0,0,1,0}, + {"f",0,0,1,0,0}, + {"F",0,0,1,0,0}, + {"o:",0,0,1,1,"filter.out"}, + {"q",0,0,1,0,0}, + {"M",0,0,0,1,0}, + {"I",0,0,1,0,0}, + {"V",0,0,0,1,0}, + {"g",0,0,0,1,0}, + {"G",0,0,0,1,0}, + {"T:",0,0,1,0,"B"}, + {"7",0,0,0,1,0}, + {"v",0,0,0,1,0} +}; +char* grib_tool_description="Apply the rules defined in rules_file to each grib " + "message\n\tin the grib files provided as arguments."; +char* grib_tool_name="bufr_filter"; +char* grib_tool_usage="[options] rules_file " + "file file ..."; +int fail=0; +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); + +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { + + options->action = grib_action_from_filter(options->infile_extra->name); + if (!options->action) { + fprintf(stderr,"%s: error unable to create action\n",options->infile_extra->name); + exit(1); + } + + if ( options->outfile && options->outfile->name ) + options->action->context->outfilename=options->outfile->name; + + return 0; +} + +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; +} + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + int err=0; + + if (options->current_infile->name) { + size_t len=strlen(options->current_infile->name); + grib_set_string(h,"file",options->current_infile->name,&len); + } + + err=grib_handle_apply_action(h,options->action); + if (err != GRIB_SUCCESS && options->fail && err!=GRIB_NOT_FOUND) { + printf("ERROR: %s\n",grib_get_error_message(err)); + exit(err); + } + return 0; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +int grib_tool_finalise_action(grib_runtime_options* options) { + grib_file_pool_clean(); + return 0; +} diff --git a/tools/bufr_get.c b/tools/bufr_get.c new file mode 100644 index 000000000..b38bafa4c --- /dev/null +++ b/tools/bufr_get.c @@ -0,0 +1,212 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_get + * + * Author: Enrico Fucile + * + * + */ + +#include "grib_tools.h" + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value*/ + {"f",0,0,0,1,0}, + {"p:",0,0,0,1,0}, + {"F:",0,0,1,1,"%g"}, + {"l:",0,0,0,1,0}, + {"P:",0,0,0,1,0}, + {"w:",0,0,0,1,0}, + {"n:",0,0,1,1,0}, + {"s:",0,0,0,1,0}, + {"V",0,0,0,1,0}, + {"W:",0,0,1,1,"8"}, + {"m",0,0,0,1,0}, + {"M",0,0,0,1,0}, + {"S",0,0,1,0,0}, + {"g",0,0,0,1,0}, + {"G",0,0,0,1,0}, + {"T:",0,0,1,0,"B"}, + {"7",0,0,0,1,0}, + {"v",0,0,1,0,0}, + {"i:",0,0,0,1,0} +}; + +char* grib_tool_description="Get values of some keys from a grib file." + "\n\tIt is similar to grib_ls, but fails returning an error code " + "\n\twhen an error occurs (e.g. key not found)."; +char* grib_tool_name="bufr_get"; +char* grib_tool_usage="[options] file file ..."; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); +double lat=0; +double lon=0; +int mode=0; +grib_nearest* n=NULL; + +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +int grib_tool_before_getopt(grib_runtime_options* options) { + options->print_keys_count=-1; + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { + char *end = NULL, *end1=NULL; + size_t size=4; + int ret=0; + double min=0,max=0; + int i=0,idx=0; + char* p=NULL; + + options->print_header=0; + options->print_statistics=0; + options->default_print_width=-1; + + if (options->latlon) { + + lat = strtod(options->latlon,&end); + if (*end != ',') { + printf("ERROR: wrong latitude value\n"); + exit(1); + } + lon= strtod(++end,&end1); + + mode=GRIB_NEAREST_SAME_POINT | GRIB_NEAREST_SAME_GRID; + + if (end1 && *end1 == ',') { + end1++; + if (*end1 != '0') { + p=end1; + while (*p != ',' && *p !='\0') p++; + if (*end1 == '4') { + options->latlon_mode=4; + } else if (*end1 == '1') { + options->latlon_mode=1; + } else { + printf("ERROR %s: wrong mode given in option -l\n",grib_tool_name); + exit(1); + } + } + if (*p == ',') { + p++; + options->latlon_mask=strdup(p); + } + } + + + } + + if (options->latlon && options->latlon_mask) { + FILE* f=NULL; + grib_handle* hh; + f=fopen(options->latlon_mask,"r"); + if(!f) { + perror(options->latlon_mask); + exit(1); + } + hh=grib_handle_new_from_file(0,f,&ret); + fclose(f); + GRIB_CHECK_NOLINE(ret,0); + n=grib_nearest_new(hh,&ret); + GRIB_CHECK_NOLINE(ret,0); + GRIB_CHECK_NOLINE(grib_nearest_find(n,hh,lat,lon,mode, + options->lats,options->lons,options->mask_values,options->distances,options->indexes,&size),0); + grib_nearest_delete(n); + n=NULL; + grib_handle_delete( hh); + + options->latlon_idx=-1; + max=options->distances[0]; + for (i=0;i<4;i++) + if (maxdistances[i]) {max=options->distances[i];idx=i;} + min=max; + for (i=0;i<4;i++) { + if ((min >= options->distances[i]) && (options->mask_values[i] >= 0.5)) { + options->latlon_idx=i; + min = options->distances[i]; + } + } + + if (options->latlon_idx<0){ + min=0; + options->latlon_idx=0; + for (i=1;i<4;i++) + if (min>options->distances[i]) { + min = options->distances[i]; + options->latlon_idx=i; + } + } + } + + return 0; +} +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; + } + + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +int grib_tool_new_handle_action(grib_runtime_options* options,grib_handle* h) { + size_t size=4; + int err = 0; + + if (!options->skip) { + if (options->set_values_count != 0) { + err=grib_set_values(h,options->set_values,options->set_values_count); + } + + if (err != GRIB_SUCCESS && options->fail) exit(err); + } + + if (options->latlon) { + int err=0; + double min; + int i; + if (!n) n=grib_nearest_new(h,&err); + GRIB_CHECK_NOLINE(err,0); + GRIB_CHECK_NOLINE(grib_nearest_find(n,h,lat,lon,mode, + options->lats,options->lons,options->values, + options->distances,options->indexes,&size),0); + min=options->distances[0]; + options->latlon_idx=0; + i=0; + for (i=1;i<4;i++) { + if (min>options->distances[i]) { + min=options->distances[i]; + options->latlon_idx=i; + } + } + + } + + return 0; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +int grib_tool_finalise_action(grib_runtime_options* options) { + + if (n) grib_nearest_delete(n); + + return 0; +} diff --git a/tools/bufr_index_build.c b/tools/bufr_index_build.c new file mode 100644 index 000000000..11a62b308 --- /dev/null +++ b/tools/bufr_index_build.c @@ -0,0 +1,140 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_copy + * + * Author: Enrico Fucile + * + * + */ + +#include "grib_tools.h" + +char* grib_tool_description="Build an index file for a set of input grib files."; +char* grib_tool_name="bufr_index_build"; +char* grib_tool_usage="[options] file file ... "; +grib_index* idx=NULL; +char* keys; +char* default_keys = "mars"; + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value */ + {"f",0,0,0,1,0}, + {"o:",0,0,1,1,"gribidx"}, + {"k:",0,0,0,1,0}, + {"V",0,0,0,1,0}, + {"T:",0,0,1,0,"B"}, + {"M",0,0,0,1,0}, + {"N",0,0,0,1,0} +}; + +int compress_index; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); + +int main(int argc, char *argv[]) { + int ret=grib_tool(argc,argv); + return ret; +} + +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { + + int ret=0; + grib_context* c=grib_context_get_default(); + + if (grib_options_on("N")) compress_index=0; + else compress_index=1; + + if (grib_options_on("k:")) + keys=grib_options_get_option("k:"); + else + keys=default_keys; + + options->onlyfiles=1; + + idx=grib_index_new(c,keys,&ret); + + if (!idx || ret) + grib_context_log(c,GRIB_LOG_FATAL, + "Unable to create index %s",grib_get_error_message(ret)); + + return 0; +} + +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + int ret=0; + printf("--- %s: processing %s\n",grib_tool_name,file); + ret=codes_index_add_file(idx,file,CODES_BUFR); + if (ret) {printf("error: %s\n",grib_get_error_message(ret)); exit(ret);} + return 0; +} + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + return 0; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { +} + +int grib_tool_finalise_action(grib_runtime_options* options) { + grib_index_key* keys; + grib_string_list* values; + int first; + + + if (compress_index) { + grib_index_compress(idx); + } + printf("--- %s: keys included in the index file %s:\n", + grib_tool_name,options->outfile->name); + printf("--- "); + first=1; + keys=idx->keys; + while (keys) { + if (!first) printf(", "); + printf("%s",keys->name); + keys=keys->next; + first=0; + } + printf("\n"); + keys=idx->keys; + while (keys) { + printf("--- %s = { ",keys->name); + values=keys->values; + first=1; + while (values) { + if (!first) printf(", "); + printf("%s",values->value); + first=0; + values=values->next; + } + printf(" }\n"); + keys=keys->next; + } + printf("--- %d messages indexed\n",idx->count); + + if (idx->count) + grib_index_write(idx,options->outfile->name); + grib_index_delete(idx); + return 0; +} diff --git a/tools/bufr_ls.c b/tools/bufr_ls.c new file mode 100644 index 000000000..7156dc359 --- /dev/null +++ b/tools/bufr_ls.c @@ -0,0 +1,350 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_ls + * + * Author: Enrico Fucile + * + * + */ +#include "grib_tools.h" + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value*/ + {"f",0,0,1,0,0}, + {"p:",0,0,0,1,0}, + {"F:",0,0,1,1,"%g"}, + {"P:",0,0,0,1,0}, + {"w:",0,0,0,1,0}, + {"j",0,"json output\n",0,1,0}, + {"B:",0,0,0,1,0}, + {"l:",0,0,0,1,0}, + {"s:",0,0,0,1,0}, + {"i:",0,0,0,1,0}, + {"n:",0,0,1,1,"ls"}, + {"m",0,0,0,1,0}, + {"V",0,0,0,1,0}, + {"W:",0,0,1,1,"10"}, + {"S",0,0,1,0,0}, + {"M",0,0,0,1,0}, + {"H",0,0,1,0,0}, + {"g",0,0,0,1,0}, + {"P",0,0,1,0,0}, + {"T:",0,0,1,0,"B"}, + {"7",0,0,0,1,0}, + {"v",0,0,1,0,0}, + {"x",0,0,0,1,0} +}; + +char* grib_tool_description="List content of grib files printing values of " + "some keys.\n\tIt does not fail when a key is not found."; +char* grib_tool_name="bufr_ls"; +char* grib_tool_usage="[options] file file ..."; +static char* new_handle=""; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); +double lat=0; +double lon=0; +int mode=0; +static int json=0; + +grib_nearest* n=NULL; +/*double *outlats,*outlons,*values,*lsm_values,*distances;*/ + +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +/* +This is executed before processing the options with i +getopt and therfore it is the right place for hacking +the arguments if needed +*/ +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +/* +The options have been parsed and the structure +grib_runtime_options* options has been loaded. +Initialization and startup can be done here +*/ +int grib_tool_init(grib_runtime_options* options) { + char *end = NULL, *end1=NULL; + size_t size=4; + int ret=0; + double min=0,max=0; + int i=0,idx=0; + char* p=NULL; + if (grib_options_on("j")) { + options->verbose=0; + json=1; + } + + if (options->latlon) { + + lat = strtod(options->latlon,&end); + if (*end != ',') { + printf("ERROR: wrong latitude value\n"); + exit(1); + } + lon= strtod(++end,&end1); + + mode=GRIB_NEAREST_SAME_POINT | GRIB_NEAREST_SAME_GRID; + + if (end1 && *end1 == ',') { + end1++; + if (*end1 != '0') { + p=end1; + while (*p != ',' && *p !='\0') p++; + if (*end1 == '4') { + options->latlon_mode=4; + } else if (*end1 == '1') { + options->latlon_mode=1; + } else { + printf("ERROR %s: wrong mode given in option -l\n",grib_tool_name); + exit(1); + } + } + if (*p == ',') { + p++; + options->latlon_mask=strdup(p); + } + } + + } + + if (options->latlon && options->latlon_mask) { + FILE* f=NULL; + grib_handle* hh; + f=fopen(options->latlon_mask,"r"); + if(!f) { + perror(options->latlon_mask); + exit(1); + } + hh=grib_handle_new_from_file(0,f,&ret); + fclose(f); + GRIB_CHECK_NOLINE(ret,0); + n=grib_nearest_new(hh,&ret); + GRIB_CHECK_NOLINE(ret,0); + GRIB_CHECK_NOLINE(grib_nearest_find(n,hh,lat,lon,mode, + options->lats,options->lons,options->mask_values,options->distances,options->indexes,&size),0); + grib_nearest_delete(n); + n=NULL; + grib_handle_delete( hh); + + options->latlon_idx=-1; + max=options->distances[0]; + for (i=0;i<4;i++) + if (maxdistances[i]) {max=options->distances[i];idx=i;} + min=max; + for (i=0;i<4;i++) { + if ((min >= options->distances[i]) && (options->mask_values[i] >= 0.5)) { + options->latlon_idx=i; + min = options->distances[i]; + } + } + + if (options->latlon_idx<0){ + min=0; + options->latlon_idx=0; + for (i=1;i<4;i++) + if (min>options->distances[i]) { + min = options->distances[i]; + options->latlon_idx=i; + } + } + } + if (json) printf("[\n"); + + return 0; +} + +/* +A new file is being parsed. The file name is file. This function is called every time +a new input file name is processed, before opening the file. +*/ +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; + } + + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +static void print_key_values(grib_runtime_options* options,grib_handle* h) { + int i; + int ret=0; + char* s="\"keys\" : {"; + double dvalue=0; + long lvalue=0; + char value[MAX_STRING_LEN]; + size_t len=MAX_STRING_LEN; + for (i=0;iprint_keys_count;i++) { + ret=GRIB_SUCCESS; + printf("%s",s); + len=MAX_STRING_LEN; + printf("\"%s\" : ",options->print_keys[i].name); + if (grib_is_missing(h,options->print_keys[i].name,&ret) && ret==GRIB_SUCCESS) + printf("\"missing\""); + else if ( ret == GRIB_SUCCESS ) { + if (options->print_keys[i].type == GRIB_TYPE_UNDEFINED) + grib_get_native_type(h,options->print_keys[i].name,&(options->print_keys[i].type)); + switch (options->print_keys[i].type) { + case GRIB_TYPE_STRING: + ret=grib_get_string( h,options->print_keys[i].name,value,&len); + printf("\"%s\"",value); + break; + case GRIB_TYPE_DOUBLE: + ret=grib_get_double( h,options->print_keys[i].name,&dvalue); + printf("%g",dvalue); + break; + case GRIB_TYPE_LONG: + ret=grib_get_long( h,options->print_keys[i].name,&lvalue); + printf("%ld",lvalue); + break; + default: + printf("invalid_type"); + } + } + if (ret == GRIB_NOT_FOUND) printf("null"); + s=", "; + } + printf("}"); +} + +/* A new handle is available from the current input file and can be processed here. +The handle available in this function is in the set of messages satisfying the constrant of the +-w option. They are not to be skipped. +*/ +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + size_t size=4; + double v=0; + int err=0; + int i; + + if (!options->skip) { + + if (options->set_values_count != 0) + err=grib_set_values(h,options->set_values,options->set_values_count); + + if( err != GRIB_SUCCESS && options->fail) exit(err); + } + + if (options->latlon) { + int err=0; + double min; + if (!n) n=grib_nearest_new(h,&err); + GRIB_CHECK_NOLINE(err,0); + GRIB_CHECK_NOLINE(grib_nearest_find(n,h,lat,lon,0, + options->lats,options->lons,options->values, + options->distances,options->indexes,&size),0); + + if (!options->latlon_mask) { + min=options->distances[0]; + options->latlon_idx=0; + i=0; + for (i=1;i<4;i++) { + if (min>options->distances[i]) { + min=options->distances[i]; + options->latlon_idx=i; + } + } + } + + if (json) { + char* s="\n[\n"; + double missingValue=9999; + char value[MAX_STRING_LEN]; + size_t len=MAX_STRING_LEN; + printf("%s",new_handle); + printf( "{\n"); + print_key_values(options,h); + printf("\n, \"selected\" : %d",options->latlon_idx); + printf(", \"method\" : "); + if (options->latlon_mask) printf("\"nearest_land\""); + else printf("\"nearest\""); + printf("\n, \"neighbours\" : "); + for (i=0;i<4;i++) { + printf("%s",s); + len=MAX_STRING_LEN; + printf("{\"index\" : %d, \"latitude\" : %g, \"longitude\" : %g, \"distance\" : %g, " + "\"distance_unit\" : \"km\", ", + (int)options->indexes[i],options->lats[i],options->lons[i], + options->distances[i]); + if (grib_get_double_element(h,"values",options->indexes[i],&v) == GRIB_SUCCESS) { + if (v==missingValue) printf("\"value\" : null "); + else printf("\"value\" : %g ",v); + } + + if (grib_get_string( h,"units",value,&len)==GRIB_SUCCESS) + printf(", \"unit\" : \"%s\"",value); + + if (options->latlon_mask) + printf(", \"mask_value\"=%.2f",options->mask_values[i]); + printf("}"); + s="\n,"; + } + + printf("\n]"); + printf("\n}"); + } + + } + new_handle="\n,"; + return 0; +} + +/* A new handle to skip is available. At this point something can be done +with the message to be skipped before deleting the handle. */ +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +/* key values can be printed in this function. Headers are already printed if requested.*/ +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +/* this is executed after the last message in the last file is processed */ +int grib_tool_finalise_action(grib_runtime_options* options) { + int i=0; + if (options->latlon && options->verbose) { + + printf("Input Point: latitude=%.2f longitude=%.2f\n",lat,lon); + printf("Grid Point chosen #%d index=%d latitude=%.2f longitude=%.2f distance=%.2f (Km)\n", + options->latlon_idx+1,(int)options->indexes[options->latlon_idx], + options->lats[options->latlon_idx], + options->lons[options->latlon_idx], + options->distances[options->latlon_idx]); + + if (options->latlon_mask) { + printf("Mask values:\n"); + for (i=0;i<4;i++) { + printf("- %d - index=%d latitude=%.2f longitude=%.2f distance=%.2f (Km) value=%.2f\n", + i+1,(int)options->indexes[i],options->lats[i],options->lons[i], + options->distances[i],options->mask_values[i]); + } + } else { + printf("Other grid Points\n"); + for (i=0;i<4;i++) { + printf("- %d - index=%d latitude=%.2f longitude=%.2f distance=%.2f (Km)\n", + i+1,(int)options->indexes[i],options->lats[i],options->lons[i], + options->distances[i]); + } + } + } + + if (n) grib_nearest_delete(n); + if (json) printf("\n]\n"); + + return 0; +} diff --git a/tools/bufr_set.c b/tools/bufr_set.c new file mode 100644 index 000000000..1a4af02a2 --- /dev/null +++ b/tools/bufr_set.c @@ -0,0 +1,161 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_set + * + * Author: Enrico Fucile + * + * + */ +#include "grib_tools.h" + +grib_option grib_options[]={ + /* {id, args, help}, on, command_line, value*/ + {"s:",0,0,1,1,0}, + {"r",0,0,0,1,0}, + {"d:",0,0,0,1,0}, + /*{"n:","noise percentage","\n\t\tAdd noise to the data values. The noise added is the given percentage of the data value.\n",0,1,0},*/ + {"p:",0,0,1,1,0}, + {"P:",0,0,0,1,0}, + {"w:","key[:{s/d/l}]=value,key[:{s/d/l}]=value,...", + "\n\t\tWhere clause.\n\t\tSet is only executed for grib messages matching all the " + "key/value constraints.\n\t\tIf a grib message does not match the constraints it is" + " copied unchanged\n\t\tto the output_grib_file. This behaviour can be changed " + "setting the option -S.\n\t\tFor each key a string (key:s) or a double (key:d) or" + " a long (key:l)\n\t\ttype can be defined. Default type is string.\n",0,1,0}, + {"q",0,0,1,0,0}, + {"7",0,0,0,1,0}, + {"S",0,0,0,1,0}, + {"U",0,0,1,0,0}, + {"V",0,0,0,1,0}, + {"M",0,0,0,1,0}, + {"g",0,0,0,1,0}, + {"G",0,0,0,1,0}, + {"T:",0,0,1,0,"B"}, + {"f",0,0,0,1,0}, + {"v",0,0,0,1,0} +}; + +char* grib_tool_description="Sets key/value pairs in the input grib file and writes" +"\n\teach message to the output_grib_file." +"\n\tIt fails when an error occurs (e.g. key not found)."; +char* grib_tool_name="bufr_set"; +char* grib_tool_usage="[options] file file ... output_file"; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); + +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { + if (options->set_values_count == 0 && !options->repack && !options->constant) { + printf("ERROR: please provide some keys to set through the -s option or use the -r/-d options\n"); + exit(1); + } + if (options->verbose) options->print_header=1; + /*if (grib_options_on("n:")) { + noise=atof(grib_options_get_option("n:")); + options->repack=1; + }*/ + + if (grib_options_on("n:") && grib_options_on("d:")) { + printf("Error: -n and -d options are incompatible. Choose one of the two please.\n"); + exit(1); + } + +#if 0 + if (options->outfile && options->outfile->name) { + options->outfile->file = fopen(options->outfile->name,"w"); + if(!options->outfile->file) { + perror(options->outfile->name); + exit(1); + } + } +#endif + return 0; +} + +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; + } + + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + + int i=0; + int err=0; + + if (!options->skip) { + double* v=NULL; + size_t size=0; + if ( options->repack ) { + GRIB_CHECK_NOLINE(grib_get_size(h,"values",&size),0); + + v = (double*)calloc(size,sizeof(double)); + if(!v) { + fprintf(stderr,"failed to allocate %d bytes\n",(int)(size*sizeof(double))); + exit(1); + } + + GRIB_CHECK_NOLINE(grib_get_double_array(h,"values",v,&size),0); + } + + if (options->set_values_count != 0) + err=grib_set_values(h,options->set_values,options->set_values_count); + + if ( options->repack ) { + + if (grib_options_on("d:")) { + for(i = 0; i< size; i++) + v[i] = options->constant; + } +#if 0 + if (grib_options_on("n:")) { + for(i = 0; i< size; i++) + v[i] = options->constant; + } +#endif + + GRIB_CHECK_NOLINE(grib_set_double_array(h,"values",v,size),0); + free(v); + } + + if( err != GRIB_SUCCESS && options->fail) exit(err); + } + + if (!options->skip || !options->strict) grib_tools_write_message(options,h); + + return 0; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + + +int grib_tool_finalise_action(grib_runtime_options* options) { + return 0; +} + + + diff --git a/tools/metar_dump.c b/tools/metar_dump.c new file mode 100644 index 000000000..1023d810b --- /dev/null +++ b/tools/metar_dump.c @@ -0,0 +1,170 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_dump + * + * Author: Enrico Fucile + * + * + */ + +#include "grib_tools.h" + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value*/ + {"S",0,0,1,0,0}, + {"O",0,"Octet mode. WMO documentation style dump.\n",0,1,0}, + {"D",0,0,0,1,0}, + {"d",0,"Print all data values.\n",0,1,0}, + {"C",0,0,0,1,0}, + {"t",0,0,0,1,0}, + {"j",0,0,0,1,0}, + {"H",0,0,0,1,0}, + {"a",0,0,0,1,0}, + {"w:",0,0,0,1,0}, + {"M",0,0,0,1,0}, + {"T:",0,0,1,0,"M"}, + {"7",0,0,0,1,0}, + {"V",0,0,0,1,0}, + {"q",0,0,1,0,0}, + {"x",0,0,0,1,0} +}; + +char* grib_tool_description="Dump the content of a grib file in different formats."; +char* grib_tool_name="metar_dump"; +char* grib_tool_usage="[options] file file ..."; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); + +/** +*grib_dump +*Dump the content of a grib file +* +*/ +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { + + int opt=grib_options_on("C")+grib_options_on("O")+grib_options_on("D"); + + options->dump_mode = "default"; + + + if (opt > 1) { + printf("%s: simultaneous C/O/D options not allowed\n",grib_tool_name); + exit(1); + } + + if (grib_options_on("C")) { + options->dump_mode = "c_code"; + if (grib_options_on("d")) + options->dump_flags = 0; + else + options->dump_flags = GRIB_DUMP_FLAG_NO_DATA; + } + + if (grib_options_on("O")) { + options->dump_mode = "wmo"; + options->dump_flags = GRIB_DUMP_FLAG_CODED + | GRIB_DUMP_FLAG_OCTECT + | GRIB_DUMP_FLAG_VALUES + | GRIB_DUMP_FLAG_READ_ONLY; + } + + if (grib_options_on("D")) { + options->dump_mode = "debug"; + options->dump_flags = GRIB_DUMP_FLAG_VALUES + | GRIB_DUMP_FLAG_READ_ONLY; + } + + if (grib_options_on("J")) { + options->dump_mode = "json"; + options->dump_flags = GRIB_DUMP_FLAG_VALUES + | GRIB_DUMP_FLAG_READ_ONLY; + } + + if (grib_options_on("X")) { + options->dump_mode = "xml"; + options->dump_flags = GRIB_DUMP_FLAG_VALUES + | GRIB_DUMP_FLAG_READ_ONLY; + } + + if (grib_options_on("a")) + options->dump_flags |= GRIB_DUMP_FLAG_ALIASES; + + if (grib_options_on("t")) + options->dump_flags |= GRIB_DUMP_FLAG_TYPE; + + if (grib_options_on("H")) + options->dump_flags |= GRIB_DUMP_FLAG_HEXADECIMAL; + + if (grib_options_on("d")) + options->dump_flags |= GRIB_DUMP_FLAG_ALL_DATA; + + return 0; +} + +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; +} + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + char tmp[1024]; + if (!options->current_infile->name) return 0; + sprintf(tmp,"FILE: %s ",options->current_infile->name); + if (!grib_options_on("C") && !grib_options_on("J") && !grib_options_on("X") ) + fprintf(stdout,"***** %s\n",tmp); + return 0; +} + +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + long length=0; + char tmp[1024]; + char identifier[100]; + size_t idlen=100; + int i; + if (grib_get_long(h,"totalLength",&length) != GRIB_SUCCESS) + length=-9999; + + for (i=0;iprint_keys_count;i++) + grib_set_flag(h,options->print_keys[i].name,GRIB_ACCESSOR_FLAG_DUMP); + + sprintf(tmp,"MESSAGE %d ( length=%ld )",options->handle_count,length); + if (!grib_options_on("C") && !grib_options_on("X") && !grib_options_on("J") ) + fprintf(stdout,"#============== %-38s ==============\n",tmp); + if (!strcmp(options->dump_mode,"default")) { + GRIB_CHECK_NOLINE(grib_get_string(h,"identifier",identifier,&idlen),0); + printf("%s {\n",identifier); + } + + grib_dump_content(h,stdout,options->dump_mode,options->dump_flags,0); + + if (!strcmp(options->dump_mode,"default")) + printf("}\n"); + return 0; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +int grib_tool_finalise_action(grib_runtime_options* options) { + return 0; +} diff --git a/tools/metar_filter.c b/tools/metar_filter.c new file mode 100644 index 000000000..386e37f06 --- /dev/null +++ b/tools/metar_filter.c @@ -0,0 +1,102 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_filter + * + * Author: Enrico Fucile + * + * + */ + +#include "grib_tools.h" + + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value */ + {"f",0,0,0,1,0}, + {"f",0,0,1,0,0}, + {"F",0,0,1,0,0}, + {"o:",0,0,1,1,"filter.out"}, + {"q",0,0,1,0,0}, + {"M",0,0,0,1,0}, + {"I",0,0,1,0,0}, + {"V",0,0,0,1,0}, + {"g",0,0,0,1,0}, + {"G",0,0,0,1,0}, + {"T:",0,0,1,0,"M"}, + {"7",0,0,0,1,0}, + {"v",0,0,0,1,0} +}; +char* grib_tool_description="Apply the rules defined in rules_file to each metar " + "message\n\tin the files provided as arguments."; +char* grib_tool_name="metar_filter"; +char* grib_tool_usage="[options] rules_file " + "file file ..."; +int fail=0; +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); + +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { + + options->action = grib_action_from_filter(options->infile_extra->name); + if (!options->action) { + fprintf(stderr,"%s: error unable to create action\n",options->infile_extra->name); + exit(1); + } + + if ( options->outfile && options->outfile->name ) + options->action->context->outfilename=options->outfile->name; + + return 0; +} + +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; +} + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + int err=0; + + if (options->current_infile->name) { + size_t len=strlen(options->current_infile->name); + grib_set_string(h,"file",options->current_infile->name,&len); + } + + err=grib_handle_apply_action(h,options->action); + if (err != GRIB_SUCCESS && options->fail && err!=GRIB_NOT_FOUND) { + printf("ERROR: %s\n",grib_get_error_message(err)); + exit(err); + } + return 0; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +int grib_tool_finalise_action(grib_runtime_options* options) { + grib_file_pool_clean(); + return 0; +} diff --git a/tools/metar_get.c b/tools/metar_get.c new file mode 100644 index 000000000..9a207ec01 --- /dev/null +++ b/tools/metar_get.c @@ -0,0 +1,212 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_get + * + * Author: Enrico Fucile + * + * + */ + +#include "grib_tools.h" + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value*/ + {"f",0,0,0,1,0}, + {"p:",0,0,0,1,0}, + {"F:",0,0,1,1,"%g"}, + {"l:",0,0,0,1,0}, + {"P:",0,0,0,1,0}, + {"w:",0,0,0,1,0}, + {"n:",0,0,1,1,0}, + {"s:",0,0,0,1,0}, + {"V",0,0,0,1,0}, + {"W:",0,0,1,1,"8"}, + {"m",0,0,0,1,0}, + {"M",0,0,0,1,0}, + {"S",0,0,1,0,0}, + {"g",0,0,0,1,0}, + {"G",0,0,0,1,0}, + {"T:",0,0,1,0,"M"}, + {"7",0,0,0,1,0}, + {"v",0,0,1,0,0}, + {"i:",0,0,0,1,0} +}; + +char* grib_tool_description="Get values of some keys from a metar file." + "\n\tIt is similar to metar_ls, but fails returning an error code " + "\n\twhen an error occurs (e.g. key not found)."; +char* grib_tool_name="metar_get"; +char* grib_tool_usage="[options] file file ..."; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); +double lat=0; +double lon=0; +int mode=0; +grib_nearest* n=NULL; + +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +int grib_tool_before_getopt(grib_runtime_options* options) { + options->print_keys_count=-1; + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { + char *end = NULL, *end1=NULL; + size_t size=4; + int ret=0; + double min=0,max=0; + int i=0,idx=0; + char* p=NULL; + + options->print_header=0; + options->print_statistics=0; + options->default_print_width=-1; + + if (options->latlon) { + + lat = strtod(options->latlon,&end); + if (*end != ',') { + printf("ERROR: wrong latitude value\n"); + exit(1); + } + lon= strtod(++end,&end1); + + mode=GRIB_NEAREST_SAME_POINT | GRIB_NEAREST_SAME_GRID; + + if (end1 && *end1 == ',') { + end1++; + if (*end1 != '0') { + p=end1; + while (*p != ',' && *p !='\0') p++; + if (*end1 == '4') { + options->latlon_mode=4; + } else if (*end1 == '1') { + options->latlon_mode=1; + } else { + printf("ERROR %s: wrong mode given in option -l\n",grib_tool_name); + exit(1); + } + } + if (*p == ',') { + p++; + options->latlon_mask=strdup(p); + } + } + + + } + + if (options->latlon && options->latlon_mask) { + FILE* f=NULL; + grib_handle* hh; + f=fopen(options->latlon_mask,"r"); + if(!f) { + perror(options->latlon_mask); + exit(1); + } + hh=grib_handle_new_from_file(0,f,&ret); + fclose(f); + GRIB_CHECK_NOLINE(ret,0); + n=grib_nearest_new(hh,&ret); + GRIB_CHECK_NOLINE(ret,0); + GRIB_CHECK_NOLINE(grib_nearest_find(n,hh,lat,lon,mode, + options->lats,options->lons,options->mask_values,options->distances,options->indexes,&size),0); + grib_nearest_delete(n); + n=NULL; + grib_handle_delete( hh); + + options->latlon_idx=-1; + max=options->distances[0]; + for (i=0;i<4;i++) + if (maxdistances[i]) {max=options->distances[i];idx=i;} + min=max; + for (i=0;i<4;i++) { + if ((min >= options->distances[i]) && (options->mask_values[i] >= 0.5)) { + options->latlon_idx=i; + min = options->distances[i]; + } + } + + if (options->latlon_idx<0){ + min=0; + options->latlon_idx=0; + for (i=1;i<4;i++) + if (min>options->distances[i]) { + min = options->distances[i]; + options->latlon_idx=i; + } + } + } + + return 0; +} +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; + } + + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +int grib_tool_new_handle_action(grib_runtime_options* options,grib_handle* h) { + size_t size=4; + int err = 0; + + if (!options->skip) { + if (options->set_values_count != 0) { + err=grib_set_values(h,options->set_values,options->set_values_count); + } + + if (err != GRIB_SUCCESS && options->fail) exit(err); + } + + if (options->latlon) { + int err=0; + double min; + int i; + if (!n) n=grib_nearest_new(h,&err); + GRIB_CHECK_NOLINE(err,0); + GRIB_CHECK_NOLINE(grib_nearest_find(n,h,lat,lon,mode, + options->lats,options->lons,options->values, + options->distances,options->indexes,&size),0); + min=options->distances[0]; + options->latlon_idx=0; + i=0; + for (i=1;i<4;i++) { + if (min>options->distances[i]) { + min=options->distances[i]; + options->latlon_idx=i; + } + } + + } + + return 0; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +int grib_tool_finalise_action(grib_runtime_options* options) { + + if (n) grib_nearest_delete(n); + + return 0; +} diff --git a/tools/metar_ls.c b/tools/metar_ls.c new file mode 100644 index 000000000..8d1aa0239 --- /dev/null +++ b/tools/metar_ls.c @@ -0,0 +1,350 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_ls + * + * Author: Enrico Fucile + * + * + */ +#include "grib_tools.h" + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value*/ + {"f",0,0,1,0,0}, + {"p:",0,0,0,1,0}, + {"F:",0,0,1,1,"%g"}, + {"P:",0,0,0,1,0}, + {"w:",0,0,0,1,0}, + {"j",0,"json output\n",0,1,0}, + {"B:",0,0,0,1,0}, + {"l:",0,0,0,1,0}, + {"s:",0,0,0,1,0}, + {"i:",0,0,0,1,0}, + {"n:",0,0,1,1,"ls"}, + {"m",0,0,0,1,0}, + {"V",0,0,0,1,0}, + {"W:",0,0,1,1,"10"}, + {"S",0,0,1,0,0}, + {"M",0,0,0,1,0}, + {"H",0,0,1,0,0}, + {"g",0,0,0,1,0}, + {"P",0,0,1,0,0}, + {"T:",0,0,1,0,"M"}, + {"7",0,0,0,1,0}, + {"v",0,0,1,0,0}, + {"x",0,0,0,1,0} +}; + +char* grib_tool_description="List content of metar files printing values of " + "some keys.\n\tIt does not fail when a key is not found."; +char* grib_tool_name="metar_ls"; +char* grib_tool_usage="[options] file file ..."; +static char* new_handle=""; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); +double lat=0; +double lon=0; +int mode=0; +static int json=0; + +grib_nearest* n=NULL; +/*double *outlats,*outlons,*values,*lsm_values,*distances;*/ + +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +/* +This is executed before processing the options with i +getopt and therfore it is the right place for hacking +the arguments if needed +*/ +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +/* +The options have been parsed and the structure +grib_runtime_options* options has been loaded. +Initialization and startup can be done here +*/ +int grib_tool_init(grib_runtime_options* options) { + char *end = NULL, *end1=NULL; + size_t size=4; + int ret=0; + double min=0,max=0; + int i=0,idx=0; + char* p=NULL; + if (grib_options_on("j")) { + options->verbose=0; + json=1; + } + + if (options->latlon) { + + lat = strtod(options->latlon,&end); + if (*end != ',') { + printf("ERROR: wrong latitude value\n"); + exit(1); + } + lon= strtod(++end,&end1); + + mode=GRIB_NEAREST_SAME_POINT | GRIB_NEAREST_SAME_GRID; + + if (end1 && *end1 == ',') { + end1++; + if (*end1 != '0') { + p=end1; + while (*p != ',' && *p !='\0') p++; + if (*end1 == '4') { + options->latlon_mode=4; + } else if (*end1 == '1') { + options->latlon_mode=1; + } else { + printf("ERROR %s: wrong mode given in option -l\n",grib_tool_name); + exit(1); + } + } + if (*p == ',') { + p++; + options->latlon_mask=strdup(p); + } + } + + } + + if (options->latlon && options->latlon_mask) { + FILE* f=NULL; + grib_handle* hh; + f=fopen(options->latlon_mask,"r"); + if(!f) { + perror(options->latlon_mask); + exit(1); + } + hh=grib_handle_new_from_file(0,f,&ret); + fclose(f); + GRIB_CHECK_NOLINE(ret,0); + n=grib_nearest_new(hh,&ret); + GRIB_CHECK_NOLINE(ret,0); + GRIB_CHECK_NOLINE(grib_nearest_find(n,hh,lat,lon,mode, + options->lats,options->lons,options->mask_values,options->distances,options->indexes,&size),0); + grib_nearest_delete(n); + n=NULL; + grib_handle_delete( hh); + + options->latlon_idx=-1; + max=options->distances[0]; + for (i=0;i<4;i++) + if (maxdistances[i]) {max=options->distances[i];idx=i;} + min=max; + for (i=0;i<4;i++) { + if ((min >= options->distances[i]) && (options->mask_values[i] >= 0.5)) { + options->latlon_idx=i; + min = options->distances[i]; + } + } + + if (options->latlon_idx<0){ + min=0; + options->latlon_idx=0; + for (i=1;i<4;i++) + if (min>options->distances[i]) { + min = options->distances[i]; + options->latlon_idx=i; + } + } + } + if (json) printf("[\n"); + + return 0; +} + +/* +A new file is being parsed. The file name is file. This function is called every time +a new input file name is processed, before opening the file. +*/ +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; + } + + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +static void print_key_values(grib_runtime_options* options,grib_handle* h) { + int i; + int ret=0; + char* s="\"keys\" : {"; + double dvalue=0; + long lvalue=0; + char value[MAX_STRING_LEN]; + size_t len=MAX_STRING_LEN; + for (i=0;iprint_keys_count;i++) { + ret=GRIB_SUCCESS; + printf("%s",s); + len=MAX_STRING_LEN; + printf("\"%s\" : ",options->print_keys[i].name); + if (grib_is_missing(h,options->print_keys[i].name,&ret) && ret==GRIB_SUCCESS) + printf("\"missing\""); + else if ( ret == GRIB_SUCCESS ) { + if (options->print_keys[i].type == GRIB_TYPE_UNDEFINED) + grib_get_native_type(h,options->print_keys[i].name,&(options->print_keys[i].type)); + switch (options->print_keys[i].type) { + case GRIB_TYPE_STRING: + ret=grib_get_string( h,options->print_keys[i].name,value,&len); + printf("\"%s\"",value); + break; + case GRIB_TYPE_DOUBLE: + ret=grib_get_double( h,options->print_keys[i].name,&dvalue); + printf("%g",dvalue); + break; + case GRIB_TYPE_LONG: + ret=grib_get_long( h,options->print_keys[i].name,&lvalue); + printf("%ld",lvalue); + break; + default: + printf("invalid_type"); + } + } + if (ret == GRIB_NOT_FOUND) printf("null"); + s=", "; + } + printf("}"); +} + +/* A new handle is available from the current input file and can be processed here. +The handle available in this function is in the set of messages satisfying the constrant of the +-w option. They are not to be skipped. +*/ +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + size_t size=4; + double v=0; + int err=0; + int i; + + if (!options->skip) { + + if (options->set_values_count != 0) + err=grib_set_values(h,options->set_values,options->set_values_count); + + if( err != GRIB_SUCCESS && options->fail) exit(err); + } + + if (options->latlon) { + int err=0; + double min; + if (!n) n=grib_nearest_new(h,&err); + GRIB_CHECK_NOLINE(err,0); + GRIB_CHECK_NOLINE(grib_nearest_find(n,h,lat,lon,0, + options->lats,options->lons,options->values, + options->distances,options->indexes,&size),0); + + if (!options->latlon_mask) { + min=options->distances[0]; + options->latlon_idx=0; + i=0; + for (i=1;i<4;i++) { + if (min>options->distances[i]) { + min=options->distances[i]; + options->latlon_idx=i; + } + } + } + + if (json) { + char* s="\n[\n"; + double missingValue=9999; + char value[MAX_STRING_LEN]; + size_t len=MAX_STRING_LEN; + printf("%s",new_handle); + printf( "{\n"); + print_key_values(options,h); + printf("\n, \"selected\" : %d",options->latlon_idx); + printf(", \"method\" : "); + if (options->latlon_mask) printf("\"nearest_land\""); + else printf("\"nearest\""); + printf("\n, \"neighbours\" : "); + for (i=0;i<4;i++) { + printf("%s",s); + len=MAX_STRING_LEN; + printf("{\"index\" : %d, \"latitude\" : %g, \"longitude\" : %g, \"distance\" : %g, " + "\"distance_unit\" : \"km\", ", + (int)options->indexes[i],options->lats[i],options->lons[i], + options->distances[i]); + if (grib_get_double_element(h,"values",options->indexes[i],&v) == GRIB_SUCCESS) { + if (v==missingValue) printf("\"value\" : null "); + else printf("\"value\" : %g ",v); + } + + if (grib_get_string( h,"units",value,&len)==GRIB_SUCCESS) + printf(", \"unit\" : \"%s\"",value); + + if (options->latlon_mask) + printf(", \"mask_value\"=%.2f",options->mask_values[i]); + printf("}"); + s="\n,"; + } + + printf("\n]"); + printf("\n}"); + } + + } + new_handle="\n,"; + return 0; +} + +/* A new handle to skip is available. At this point something can be done +with the message to be skipped before deleting the handle. */ +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +/* key values can be printed in this function. Headers are already printed if requested.*/ +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +/* this is executed after the last message in the last file is processed */ +int grib_tool_finalise_action(grib_runtime_options* options) { + int i=0; + if (options->latlon && options->verbose) { + + printf("Input Point: latitude=%.2f longitude=%.2f\n",lat,lon); + printf("Grid Point chosen #%d index=%d latitude=%.2f longitude=%.2f distance=%.2f (Km)\n", + options->latlon_idx+1,(int)options->indexes[options->latlon_idx], + options->lats[options->latlon_idx], + options->lons[options->latlon_idx], + options->distances[options->latlon_idx]); + + if (options->latlon_mask) { + printf("Mask values:\n"); + for (i=0;i<4;i++) { + printf("- %d - index=%d latitude=%.2f longitude=%.2f distance=%.2f (Km) value=%.2f\n", + i+1,(int)options->indexes[i],options->lats[i],options->lons[i], + options->distances[i],options->mask_values[i]); + } + } else { + printf("Other grid Points\n"); + for (i=0;i<4;i++) { + printf("- %d - index=%d latitude=%.2f longitude=%.2f distance=%.2f (Km)\n", + i+1,(int)options->indexes[i],options->lats[i],options->lons[i], + options->distances[i]); + } + } + } + + if (n) grib_nearest_delete(n); + if (json) printf("\n]\n"); + + return 0; +} diff --git a/tools/taf_dump.c b/tools/taf_dump.c new file mode 100644 index 000000000..bf5b863ce --- /dev/null +++ b/tools/taf_dump.c @@ -0,0 +1,169 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_dump + * + * Author: Enrico Fucile + * + * + */ + +#include "grib_tools.h" + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value*/ + {"S",0,0,1,0,0}, + {"O",0,"Octet mode. WMO documentation style dump.\n",0,1,0}, + {"D",0,0,0,1,0}, + {"d",0,"Print all data values.\n",0,1,0}, + {"C",0,0,0,1,0}, + {"t",0,0,0,1,0}, + {"H",0,0,0,1,0}, + {"a",0,0,0,1,0}, + {"w:",0,0,0,1,0}, + {"M",0,0,0,1,0}, + {"T:",0,0,1,0,"F"}, + {"7",0,0,0,1,0}, + {"V",0,0,0,1,0}, + {"q",0,0,1,0,0}, + {"x",0,0,0,1,0} +}; + +char* grib_tool_description="Dump the content of a grib file in different formats."; +char* grib_tool_name="taf_dump"; +char* grib_tool_usage="[options] file file ..."; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); + +/** +*grib_dump +*Dump the content of a grib file +* +*/ +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { + + int opt=grib_options_on("C")+grib_options_on("O")+grib_options_on("D"); + + options->dump_mode = "default"; + + + if (opt > 1) { + printf("%s: simultaneous C/O/D options not allowed\n",grib_tool_name); + exit(1); + } + + if (grib_options_on("C")) { + options->dump_mode = "c_code"; + if (grib_options_on("d")) + options->dump_flags = 0; + else + options->dump_flags = GRIB_DUMP_FLAG_NO_DATA; + } + + if (grib_options_on("O")) { + options->dump_mode = "wmo"; + options->dump_flags = GRIB_DUMP_FLAG_CODED + | GRIB_DUMP_FLAG_OCTECT + | GRIB_DUMP_FLAG_VALUES + | GRIB_DUMP_FLAG_READ_ONLY; + } + + if (grib_options_on("D")) { + options->dump_mode = "debug"; + options->dump_flags = GRIB_DUMP_FLAG_VALUES + | GRIB_DUMP_FLAG_READ_ONLY; + } + + if (grib_options_on("J")) { + options->dump_mode = "json"; + options->dump_flags = GRIB_DUMP_FLAG_VALUES + | GRIB_DUMP_FLAG_READ_ONLY; + } + + if (grib_options_on("X")) { + options->dump_mode = "xml"; + options->dump_flags = GRIB_DUMP_FLAG_VALUES + | GRIB_DUMP_FLAG_READ_ONLY; + } + + if (grib_options_on("a")) + options->dump_flags |= GRIB_DUMP_FLAG_ALIASES; + + if (grib_options_on("t")) + options->dump_flags |= GRIB_DUMP_FLAG_TYPE; + + if (grib_options_on("H")) + options->dump_flags |= GRIB_DUMP_FLAG_HEXADECIMAL; + + if (grib_options_on("d")) + options->dump_flags |= GRIB_DUMP_FLAG_ALL_DATA; + + return 0; +} + +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; +} + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + char tmp[1024]; + if (!options->current_infile->name) return 0; + sprintf(tmp,"FILE: %s ",options->current_infile->name); + if (!grib_options_on("C") && !grib_options_on("J") && !grib_options_on("X") ) + fprintf(stdout,"***** %s\n",tmp); + return 0; +} + +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + long length=0; + char tmp[1024]; + char identifier[100]; + size_t idlen=100; + int i; + if (grib_get_long(h,"totalLength",&length) != GRIB_SUCCESS) + length=-9999; + + for (i=0;iprint_keys_count;i++) + grib_set_flag(h,options->print_keys[i].name,GRIB_ACCESSOR_FLAG_DUMP); + + sprintf(tmp,"MESSAGE %d ( length=%ld )",options->handle_count,length); + if (!grib_options_on("C") && !grib_options_on("X") && !grib_options_on("J") ) + fprintf(stdout,"#============== %-38s ==============\n",tmp); + if (!strcmp(options->dump_mode,"default")) { + GRIB_CHECK_NOLINE(grib_get_string(h,"identifier",identifier,&idlen),0); + printf("%s {\n",identifier); + } + + grib_dump_content(h,stdout,options->dump_mode,options->dump_flags,0); + + if (!strcmp(options->dump_mode,"default")) + printf("}\n"); + return 0; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +int grib_tool_finalise_action(grib_runtime_options* options) { + return 0; +} diff --git a/tools/taf_filter.c b/tools/taf_filter.c new file mode 100644 index 000000000..61fefa1f3 --- /dev/null +++ b/tools/taf_filter.c @@ -0,0 +1,102 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_filter + * + * Author: Enrico Fucile + * + * + */ + +#include "grib_tools.h" + + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value */ + {"f",0,0,0,1,0}, + {"f",0,0,1,0,0}, + {"F",0,0,1,0,0}, + {"o:",0,0,1,1,"filter.out"}, + {"q",0,0,1,0,0}, + {"M",0,0,0,1,0}, + {"I",0,0,1,0,0}, + {"V",0,0,0,1,0}, + {"g",0,0,0,1,0}, + {"G",0,0,0,1,0}, + {"T:",0,0,1,0,"F"}, + {"7",0,0,0,1,0}, + {"v",0,0,0,1,0} +}; +char* grib_tool_description="Apply the rules defined in rules_file to each taf " + "message\n\tin the files provided as arguments."; +char* grib_tool_name="taf_filter"; +char* grib_tool_usage="[options] rules_file " + "file file ..."; +int fail=0; +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); + +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { + + options->action = grib_action_from_filter(options->infile_extra->name); + if (!options->action) { + fprintf(stderr,"%s: error unable to create action\n",options->infile_extra->name); + exit(1); + } + + if ( options->outfile && options->outfile->name ) + options->action->context->outfilename=options->outfile->name; + + return 0; +} + +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; +} + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + int err=0; + + if (options->current_infile->name) { + size_t len=strlen(options->current_infile->name); + grib_set_string(h,"file",options->current_infile->name,&len); + } + + err=grib_handle_apply_action(h,options->action); + if (err != GRIB_SUCCESS && options->fail && err!=GRIB_NOT_FOUND) { + printf("ERROR: %s\n",grib_get_error_message(err)); + exit(err); + } + return 0; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +int grib_tool_finalise_action(grib_runtime_options* options) { + grib_file_pool_clean(); + return 0; +} diff --git a/tools/taf_get.c b/tools/taf_get.c new file mode 100644 index 000000000..6c0b003d7 --- /dev/null +++ b/tools/taf_get.c @@ -0,0 +1,212 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_get + * + * Author: Enrico Fucile + * + * + */ + +#include "grib_tools.h" + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value*/ + {"f",0,0,0,1,0}, + {"p:",0,0,0,1,0}, + {"F:",0,0,1,1,"%g"}, + {"l:",0,0,0,1,0}, + {"P:",0,0,0,1,0}, + {"w:",0,0,0,1,0}, + {"n:",0,0,1,1,0}, + {"s:",0,0,0,1,0}, + {"V",0,0,0,1,0}, + {"W:",0,0,1,1,"8"}, + {"m",0,0,0,1,0}, + {"M",0,0,0,1,0}, + {"S",0,0,1,0,0}, + {"g",0,0,0,1,0}, + {"G",0,0,0,1,0}, + {"T:",0,0,1,0,"F"}, + {"7",0,0,0,1,0}, + {"v",0,0,1,0,0}, + {"i:",0,0,0,1,0} +}; + +char* grib_tool_description="Get values of some keys from a taf file." + "\n\tIt is similar to taf_ls, but fails returning an error code " + "\n\twhen an error occurs (e.g. key not found)."; +char* grib_tool_name="taf_get"; +char* grib_tool_usage="[options] file file ..."; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); +double lat=0; +double lon=0; +int mode=0; +grib_nearest* n=NULL; + +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +int grib_tool_before_getopt(grib_runtime_options* options) { + options->print_keys_count=-1; + return 0; +} + +int grib_tool_init(grib_runtime_options* options) { + char *end = NULL, *end1=NULL; + size_t size=4; + int ret=0; + double min=0,max=0; + int i=0,idx=0; + char* p=NULL; + + options->print_header=0; + options->print_statistics=0; + options->default_print_width=-1; + + if (options->latlon) { + + lat = strtod(options->latlon,&end); + if (*end != ',') { + printf("ERROR: wrong latitude value\n"); + exit(1); + } + lon= strtod(++end,&end1); + + mode=GRIB_NEAREST_SAME_POINT | GRIB_NEAREST_SAME_GRID; + + if (end1 && *end1 == ',') { + end1++; + if (*end1 != '0') { + p=end1; + while (*p != ',' && *p !='\0') p++; + if (*end1 == '4') { + options->latlon_mode=4; + } else if (*end1 == '1') { + options->latlon_mode=1; + } else { + printf("ERROR %s: wrong mode given in option -l\n",grib_tool_name); + exit(1); + } + } + if (*p == ',') { + p++; + options->latlon_mask=strdup(p); + } + } + + + } + + if (options->latlon && options->latlon_mask) { + FILE* f=NULL; + grib_handle* hh; + f=fopen(options->latlon_mask,"r"); + if(!f) { + perror(options->latlon_mask); + exit(1); + } + hh=grib_handle_new_from_file(0,f,&ret); + fclose(f); + GRIB_CHECK_NOLINE(ret,0); + n=grib_nearest_new(hh,&ret); + GRIB_CHECK_NOLINE(ret,0); + GRIB_CHECK_NOLINE(grib_nearest_find(n,hh,lat,lon,mode, + options->lats,options->lons,options->mask_values,options->distances,options->indexes,&size),0); + grib_nearest_delete(n); + n=NULL; + grib_handle_delete( hh); + + options->latlon_idx=-1; + max=options->distances[0]; + for (i=0;i<4;i++) + if (maxdistances[i]) {max=options->distances[i];idx=i;} + min=max; + for (i=0;i<4;i++) { + if ((min >= options->distances[i]) && (options->mask_values[i] >= 0.5)) { + options->latlon_idx=i; + min = options->distances[i]; + } + } + + if (options->latlon_idx<0){ + min=0; + options->latlon_idx=0; + for (i=1;i<4;i++) + if (min>options->distances[i]) { + min = options->distances[i]; + options->latlon_idx=i; + } + } + } + + return 0; +} +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; + } + + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +int grib_tool_new_handle_action(grib_runtime_options* options,grib_handle* h) { + size_t size=4; + int err = 0; + + if (!options->skip) { + if (options->set_values_count != 0) { + err=grib_set_values(h,options->set_values,options->set_values_count); + } + + if (err != GRIB_SUCCESS && options->fail) exit(err); + } + + if (options->latlon) { + int err=0; + double min; + int i; + if (!n) n=grib_nearest_new(h,&err); + GRIB_CHECK_NOLINE(err,0); + GRIB_CHECK_NOLINE(grib_nearest_find(n,h,lat,lon,mode, + options->lats,options->lons,options->values, + options->distances,options->indexes,&size),0); + min=options->distances[0]; + options->latlon_idx=0; + i=0; + for (i=1;i<4;i++) { + if (min>options->distances[i]) { + min=options->distances[i]; + options->latlon_idx=i; + } + } + + } + + return 0; +} + +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +int grib_tool_finalise_action(grib_runtime_options* options) { + + if (n) grib_nearest_delete(n); + + return 0; +} diff --git a/tools/taf_ls.c b/tools/taf_ls.c new file mode 100644 index 000000000..0712c0125 --- /dev/null +++ b/tools/taf_ls.c @@ -0,0 +1,350 @@ +/* + * Copyright 2005-2014 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. + */ + +/* + * C Implementation: grib_ls + * + * Author: Enrico Fucile + * + * + */ +#include "grib_tools.h" + +grib_option grib_options[]={ +/* {id, args, help}, on, command_line, value*/ + {"f",0,0,1,0,0}, + {"p:",0,0,0,1,0}, + {"F:",0,0,1,1,"%g"}, + {"P:",0,0,0,1,0}, + {"w:",0,0,0,1,0}, + {"j",0,"json output\n",0,1,0}, + {"B:",0,0,0,1,0}, + {"l:",0,0,0,1,0}, + {"s:",0,0,0,1,0}, + {"i:",0,0,0,1,0}, + {"n:",0,0,1,1,"ls"}, + {"m",0,0,0,1,0}, + {"V",0,0,0,1,0}, + {"W:",0,0,1,1,"10"}, + {"S",0,0,1,0,0}, + {"M",0,0,0,1,0}, + {"H",0,0,1,0,0}, + {"g",0,0,0,1,0}, + {"P",0,0,1,0,0}, + {"T:",0,0,1,0,"F"}, + {"7",0,0,0,1,0}, + {"v",0,0,1,0,0}, + {"x",0,0,0,1,0} +}; + +char* grib_tool_description="List content of taf files printing values of " + "some keys.\n\tIt does not fail when a key is not found."; +char* grib_tool_name="taf_ls"; +char* grib_tool_usage="[options] file file ..."; +static char* new_handle=""; + +int grib_options_count=sizeof(grib_options)/sizeof(grib_option); +double lat=0; +double lon=0; +int mode=0; +static int json=0; + +grib_nearest* n=NULL; +/*double *outlats,*outlons,*values,*lsm_values,*distances;*/ + +int main(int argc, char *argv[]) { return grib_tool(argc,argv);} + +/* +This is executed before processing the options with i +getopt and therfore it is the right place for hacking +the arguments if needed +*/ +int grib_tool_before_getopt(grib_runtime_options* options) { + return 0; +} + +/* +The options have been parsed and the structure +grib_runtime_options* options has been loaded. +Initialization and startup can be done here +*/ +int grib_tool_init(grib_runtime_options* options) { + char *end = NULL, *end1=NULL; + size_t size=4; + int ret=0; + double min=0,max=0; + int i=0,idx=0; + char* p=NULL; + if (grib_options_on("j")) { + options->verbose=0; + json=1; + } + + if (options->latlon) { + + lat = strtod(options->latlon,&end); + if (*end != ',') { + printf("ERROR: wrong latitude value\n"); + exit(1); + } + lon= strtod(++end,&end1); + + mode=GRIB_NEAREST_SAME_POINT | GRIB_NEAREST_SAME_GRID; + + if (end1 && *end1 == ',') { + end1++; + if (*end1 != '0') { + p=end1; + while (*p != ',' && *p !='\0') p++; + if (*end1 == '4') { + options->latlon_mode=4; + } else if (*end1 == '1') { + options->latlon_mode=1; + } else { + printf("ERROR %s: wrong mode given in option -l\n",grib_tool_name); + exit(1); + } + } + if (*p == ',') { + p++; + options->latlon_mask=strdup(p); + } + } + + } + + if (options->latlon && options->latlon_mask) { + FILE* f=NULL; + grib_handle* hh; + f=fopen(options->latlon_mask,"r"); + if(!f) { + perror(options->latlon_mask); + exit(1); + } + hh=grib_handle_new_from_file(0,f,&ret); + fclose(f); + GRIB_CHECK_NOLINE(ret,0); + n=grib_nearest_new(hh,&ret); + GRIB_CHECK_NOLINE(ret,0); + GRIB_CHECK_NOLINE(grib_nearest_find(n,hh,lat,lon,mode, + options->lats,options->lons,options->mask_values,options->distances,options->indexes,&size),0); + grib_nearest_delete(n); + n=NULL; + grib_handle_delete( hh); + + options->latlon_idx=-1; + max=options->distances[0]; + for (i=0;i<4;i++) + if (maxdistances[i]) {max=options->distances[i];idx=i;} + min=max; + for (i=0;i<4;i++) { + if ((min >= options->distances[i]) && (options->mask_values[i] >= 0.5)) { + options->latlon_idx=i; + min = options->distances[i]; + } + } + + if (options->latlon_idx<0){ + min=0; + options->latlon_idx=0; + for (i=1;i<4;i++) + if (min>options->distances[i]) { + min = options->distances[i]; + options->latlon_idx=i; + } + } + } + if (json) printf("[\n"); + + return 0; +} + +/* +A new file is being parsed. The file name is file. This function is called every time +a new input file name is processed, before opening the file. +*/ +int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) { + return 0; + } + + +int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) { + return 0; +} + +static void print_key_values(grib_runtime_options* options,grib_handle* h) { + int i; + int ret=0; + char* s="\"keys\" : {"; + double dvalue=0; + long lvalue=0; + char value[MAX_STRING_LEN]; + size_t len=MAX_STRING_LEN; + for (i=0;iprint_keys_count;i++) { + ret=GRIB_SUCCESS; + printf("%s",s); + len=MAX_STRING_LEN; + printf("\"%s\" : ",options->print_keys[i].name); + if (grib_is_missing(h,options->print_keys[i].name,&ret) && ret==GRIB_SUCCESS) + printf("\"missing\""); + else if ( ret == GRIB_SUCCESS ) { + if (options->print_keys[i].type == GRIB_TYPE_UNDEFINED) + grib_get_native_type(h,options->print_keys[i].name,&(options->print_keys[i].type)); + switch (options->print_keys[i].type) { + case GRIB_TYPE_STRING: + ret=grib_get_string( h,options->print_keys[i].name,value,&len); + printf("\"%s\"",value); + break; + case GRIB_TYPE_DOUBLE: + ret=grib_get_double( h,options->print_keys[i].name,&dvalue); + printf("%g",dvalue); + break; + case GRIB_TYPE_LONG: + ret=grib_get_long( h,options->print_keys[i].name,&lvalue); + printf("%ld",lvalue); + break; + default: + printf("invalid_type"); + } + } + if (ret == GRIB_NOT_FOUND) printf("null"); + s=", "; + } + printf("}"); +} + +/* A new handle is available from the current input file and can be processed here. +The handle available in this function is in the set of messages satisfying the constrant of the +-w option. They are not to be skipped. +*/ +int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) { + size_t size=4; + double v=0; + int err=0; + int i; + + if (!options->skip) { + + if (options->set_values_count != 0) + err=grib_set_values(h,options->set_values,options->set_values_count); + + if( err != GRIB_SUCCESS && options->fail) exit(err); + } + + if (options->latlon) { + int err=0; + double min; + if (!n) n=grib_nearest_new(h,&err); + GRIB_CHECK_NOLINE(err,0); + GRIB_CHECK_NOLINE(grib_nearest_find(n,h,lat,lon,0, + options->lats,options->lons,options->values, + options->distances,options->indexes,&size),0); + + if (!options->latlon_mask) { + min=options->distances[0]; + options->latlon_idx=0; + i=0; + for (i=1;i<4;i++) { + if (min>options->distances[i]) { + min=options->distances[i]; + options->latlon_idx=i; + } + } + } + + if (json) { + char* s="\n[\n"; + double missingValue=9999; + char value[MAX_STRING_LEN]; + size_t len=MAX_STRING_LEN; + printf("%s",new_handle); + printf( "{\n"); + print_key_values(options,h); + printf("\n, \"selected\" : %d",options->latlon_idx); + printf(", \"method\" : "); + if (options->latlon_mask) printf("\"nearest_land\""); + else printf("\"nearest\""); + printf("\n, \"neighbours\" : "); + for (i=0;i<4;i++) { + printf("%s",s); + len=MAX_STRING_LEN; + printf("{\"index\" : %d, \"latitude\" : %g, \"longitude\" : %g, \"distance\" : %g, " + "\"distance_unit\" : \"km\", ", + (int)options->indexes[i],options->lats[i],options->lons[i], + options->distances[i]); + if (grib_get_double_element(h,"values",options->indexes[i],&v) == GRIB_SUCCESS) { + if (v==missingValue) printf("\"value\" : null "); + else printf("\"value\" : %g ",v); + } + + if (grib_get_string( h,"units",value,&len)==GRIB_SUCCESS) + printf(", \"unit\" : \"%s\"",value); + + if (options->latlon_mask) + printf(", \"mask_value\"=%.2f",options->mask_values[i]); + printf("}"); + s="\n,"; + } + + printf("\n]"); + printf("\n}"); + } + + } + new_handle="\n,"; + return 0; +} + +/* A new handle to skip is available. At this point something can be done +with the message to be skipped before deleting the handle. */ +int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) { + grib_handle_delete(h); + return 0; +} + +/* key values can be printed in this function. Headers are already printed if requested.*/ +void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) { + grib_print_key_values(options,h); +} + +/* this is executed after the last message in the last file is processed */ +int grib_tool_finalise_action(grib_runtime_options* options) { + int i=0; + if (options->latlon && options->verbose) { + + printf("Input Point: latitude=%.2f longitude=%.2f\n",lat,lon); + printf("Grid Point chosen #%d index=%d latitude=%.2f longitude=%.2f distance=%.2f (Km)\n", + options->latlon_idx+1,(int)options->indexes[options->latlon_idx], + options->lats[options->latlon_idx], + options->lons[options->latlon_idx], + options->distances[options->latlon_idx]); + + if (options->latlon_mask) { + printf("Mask values:\n"); + for (i=0;i<4;i++) { + printf("- %d - index=%d latitude=%.2f longitude=%.2f distance=%.2f (Km) value=%.2f\n", + i+1,(int)options->indexes[i],options->lats[i],options->lons[i], + options->distances[i],options->mask_values[i]); + } + } else { + printf("Other grid Points\n"); + for (i=0;i<4;i++) { + printf("- %d - index=%d latitude=%.2f longitude=%.2f distance=%.2f (Km)\n", + i+1,(int)options->indexes[i],options->lats[i],options->lons[i], + options->distances[i]); + } + } + } + + if (n) grib_nearest_delete(n); + if (json) printf("\n]\n"); + + return 0; +}