00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <glib.h>
00023 #include <utils/utils.h>
00024
00025 static char *help_msg[] = {
00026 " read_usgs - read a usgs daily values file. ",
00027 " ",
00028 " options: ",
00029 " nrecs : the number of records to read [10] ",
00030 " start : start reading the data records at the ",
00031 " : start-th record [365] ",
00032 " del : the character to delimit the output with [,]",
00033 " rm : if yes the output will be written row by ",
00034 " : row [no] ",
00035 " head : if yes, a header will be written before the ",
00036 " : data [no] ",
00037 " bo : specify the byte order of the data [be] ",
00038 " : possible values are: ",
00039 " : be - big endian ",
00040 " : le - little endian ",
00041 " units : specify the units of the source data [none] ",
00042 " : possible values are: ",
00043 " : o cfs - cubic feet per second. the ",
00044 " : equivalent si units are m^3/s. ",
00045 " : o ft - feet. the equivalent si units are",
00046 " : meters. ",
00047 " : o tn - tonnes per day. the equivalent ",
00048 " : si units are kg/s. ",
00049 " : none - no units ",
00050 " : these units will be converted to ",
00051 " : corresponding the si units. ",
00052 " scale : specify your own scale factor. this is in ",
00053 " : addition to any scaling that may be done in ",
00054 " : converting to si units. [1.] ",
00055 " fmt : specify the format of the daily values. ",
00056 " : usgs - usgs daily value format. [default] ",
00057 " : cdn - canadian daily value format. ",
00058 " v : be verbose [no] ",
00059 " ",
00060 NULL };
00061
00062 typedef struct
00063 {
00064 char blank1[2];
00065 char state[2];
00066 char agency[5];
00067 char id[15];
00068 gfloat sample_xsecloc;
00069 gfloat sample_depth;
00070 gint32 parameter;
00071 gint16 year;
00072 gint16 statistic;
00073 gfloat novalue_mark;
00074 gfloat flows[12][31];
00075 char blank2[3];
00076 char agency_office[2];
00077 char county[3];
00078 char staname[48];
00079 gfloat drain_area;
00080 gfloat cont_area;
00081 gfloat well_depth;
00082 char datum[4];
00083 gint32 hydro_unit;
00084 gint16 retrieval;
00085 gint16 start_month;
00086 char sitecode[2];
00087 char latitude[6];
00088 char longitude[7];
00089 char seqnum[2];
00090 char geo_unit[8];
00091 char blank3[2];
00092 char aquifer[1];
00093 char blank4[9];
00094 char blank5[7];
00095 }
00096 daily_val_st;
00097
00098 typedef struct
00099 {
00100 char station_number[7];
00101 gint8 parameter;
00102 gint16 year;
00103 gfloat daily_values[12][31];
00104 char flags[12][31];
00105 }
00106 daily_cdn_val_st;
00107
00108 #define METERS_PER_FOOT ( 0.3048 )
00109 #define KG_PER_TONNE_LONG ( 1.016260162601626e+03 )
00110 #define KG_PER_TONNE_SHORT ( 9.090909090909090e+02 )
00111 #define SECONDS_PER_DAY ( 86400. )
00112 #define NO_CONVERSION ( 1. )
00113
00114 int read_usgs_daily_value_record( daily_val_st *rec , FILE *fp , int byte_order );
00115 int read_cdn_daily_value_record( daily_val_st *rec , FILE *fp , int byte_order );
00116
00117 int main(int argc, char *argv[])
00118 {
00119 char *byte_order_vals[] = { "be" , "le" , NULL };
00120 char *unit_vals[] = { "none" , "cfs" , "ft" , "tn" , NULL };
00121 char *fmt_vals[] = { "usgs" , "cdn" , NULL };
00122 char *base_name;
00123 int byte_order, format, units;
00124 int n_recs, start;
00125 double scale;
00126 char *delimeter, *in_file;
00127 gboolean row_major, header;
00128 gboolean verbose;
00129 FILE *fp_in;
00130 int i, j, k;
00131 double convert_factor;
00132 double val;
00133 double time;
00134 daily_val_st *new_rec;
00135 GList *records=NULL;
00136 Eh_args *args;
00137 Eh_data_record data;
00138 GArray *data_array = g_array_new( FALSE , FALSE , sizeof(double) );
00139 GArray *time_array = g_array_new( FALSE , FALSE , sizeof(double) );
00140
00141 args = eh_opts_init(argc,argv);
00142 if ( eh_check_opts( args , NULL , NULL , help_msg )!=0 )
00143 eh_exit(-1);
00144
00145 n_recs = eh_get_opt_int ( args , "nrecs" , G_MAXINT );
00146 start = eh_get_opt_int ( args , "start" , 0 );
00147 scale = eh_get_opt_dbl ( args , "scale" , 1 );
00148 delimeter = eh_get_opt_str ( args , "del" , "," );
00149 in_file = eh_get_opt_str ( args , "in" , "-" );
00150 row_major = eh_get_opt_bool( args , "rm" , FALSE );
00151 header = eh_get_opt_bool( args , "head" , FALSE );
00152 verbose = eh_get_opt_bool( args , "v" , FALSE );
00153 byte_order = eh_get_opt_key ( args , "bo" , 0 , byte_order_vals );
00154 format = eh_get_opt_key ( args , "fmt" , 0 , fmt_vals );
00155 units = eh_get_opt_key ( args , "units" , 0 , unit_vals );
00156
00157 byte_order = (byte_order==0)?G_BIG_ENDIAN:G_LITTLE_ENDIAN;
00158 switch ( units )
00159 {
00160 case 1:
00161 convert_factor = METERS_PER_FOOT*METERS_PER_FOOT*METERS_PER_FOOT;
00162 break;
00163 case 2:
00164 convert_factor = METERS_PER_FOOT;
00165 break;
00166 case 3:
00167 convert_factor = KG_PER_TONNE_SHORT/SECONDS_PER_DAY;
00168 break;
00169 default:
00170 convert_factor = NO_CONVERSION;
00171 }
00172 convert_factor *= scale;
00173 if ( strcmp( in_file , "-" )==0 )
00174 fp_in = stdin;
00175 else
00176 fp_in = fopen( in_file , "r" );
00177
00178 if ( !fp_in )
00179 perror( in_file ), eh_exit(-1);
00180
00181 if ( verbose )
00182 {
00183 fprintf(stderr,"host byte order : %d\n",G_BYTE_ORDER);
00184 fprintf(stderr,"source byte order : %d\n",byte_order);
00185 fprintf(stderr,"source units : %s\n",unit_vals[units]);
00186 }
00187
00188
00189 data = eh_data_record_new();
00190
00191 if ( format==0 )
00192 fseek(fp_in,start*sizeof(daily_val_st),SEEK_SET);
00193 else
00194 fseek(fp_in,start*sizeof(daily_cdn_val_st),SEEK_SET);
00195
00196 for ( i=0 ; i<n_recs ; i++ )
00197 {
00198
00199 new_rec = g_new0( daily_val_st , 1 );
00200
00201
00202 if ( format==0 )
00203 read_usgs_daily_value_record( new_rec , fp_in , byte_order );
00204 else
00205 read_cdn_daily_value_record( new_rec , fp_in , byte_order );
00206
00207
00208 if ( feof(fp_in) )
00209 {
00210 fprintf(stderr,"warning : reached and of file after only %d records.\n",i);
00211 g_free(new_rec);
00212 break;
00213 }
00214
00215
00216 for ( j=0 ; j<12 ; j++ )
00217 for ( k=0 ; k<31 ; k++ )
00218 {
00219 val = new_rec->flows[j][k];
00220 if ( val > new_rec->novalue_mark+1e-5 )
00221 val *= convert_factor;
00222 time = j*31 + k + (new_rec->year-1900)*(12*31);
00223 g_array_append_val( time_array , time );
00224 g_array_append_val( data_array , val );
00225 }
00226 records = g_list_append( records , new_rec );
00227
00228 }
00229
00230 eh_data_record_add_row( data , (double*)(time_array->data) );
00231 eh_data_record_add_row( data , (double*)(data_array->data) );
00232
00233
00234
00235 new_rec = g_list_nth_data( records , 0 );
00236 eh_data_record_add_label( data , "station" , g_strndup(new_rec->staname,48) );
00237 eh_data_record_add_label( data , "site code" , g_strndup(new_rec->sitecode,2) );
00238 eh_data_record_add_label( data , "latitude" , g_strndup(new_rec->latitude,6) );
00239 eh_data_record_add_label( data , "longitude" , g_strndup(new_rec->longitude,7) );
00240 eh_data_record_add_label( data , "parameter" , g_strdup_printf("%d",new_rec->parameter) );
00241 eh_data_record_add_label( data , "statistic" , g_strdup_printf("%d",new_rec->statistic) );
00242 eh_data_record_add_label( data , "no value" , g_strdup_printf("%f",new_rec->novalue_mark) );
00243 eh_data_record_add_label( data , "start month" , g_strdup_printf("%d",new_rec->start_month) );
00244 eh_data_record_add_label( data , "start year" , g_strdup_printf("%d",new_rec->year) );
00245 eh_data_record_add_label( data , "number of years" , g_strdup_printf("%d",g_list_length(records)) );
00246
00247 base_name = g_path_get_basename( argv[0] );
00248
00249
00250 eh_data_record_print( data ,
00251 base_name ,
00252 delimeter ,
00253 row_major ,
00254 header ,
00255 stdout );
00256
00257 g_free( base_name );
00258
00259 return 0;
00260 }
00261
00262
00263 gfloat gfloat_from_le( gfloat a );
00264
00265 gfloat gfloat_from_le( gfloat a )
00266 {
00267 gint32 *dummy = (gint32*)&a;
00268 *dummy = GINT32_FROM_LE( *dummy );
00269 return a;
00270 }
00271
00272 int read_usgs_daily_value_record( daily_val_st *rec , FILE *fp , int byte_order )
00273 {
00274 int i, j;
00275 fread(rec,sizeof(daily_val_st),1,fp);
00276
00277 if ( byte_order != G_BYTE_ORDER )
00278 {
00279 rec->sample_xsecloc = gfloat_from_le(rec->sample_xsecloc);
00280 rec->sample_depth = gfloat_from_le(rec->sample_depth);
00281 rec->parameter = GINT32_FROM_LE(rec->parameter);
00282 rec->year = GINT16_FROM_LE(rec->year);
00283 rec->statistic = GINT16_FROM_LE(rec->statistic);
00284 rec->novalue_mark = gfloat_from_le(rec->novalue_mark);
00285 for ( i=0 ; i<12 ; i++ )
00286 for ( j=0 ; j<31 ; j++ )
00287 rec->flows[i][j] = gfloat_from_le(rec->flows[i][j]);
00288 rec->drain_area = gfloat_from_le(rec->drain_area);
00289 rec->cont_area = gfloat_from_le(rec->cont_area);
00290 rec->well_depth = gfloat_from_le(rec->well_depth);
00291 rec->hydro_unit = GINT32_FROM_LE(rec->hydro_unit);
00292 rec->retrieval = GINT16_FROM_LE(rec->retrieval);
00293 rec->start_month = GINT16_FROM_LE(rec->start_month);
00294
00295 }
00296
00297 return 0;
00298 }
00299
00300 int read_cdn_daily_value_record( daily_val_st *rec , FILE *fp , int byte_order )
00301 {
00302 int i, j;
00303 char *station_number = g_new0( char , 7 );
00304 gint8 parameter;
00305 gint16 year;
00306 gfloat **values;
00307 char **flags;
00308
00309 values = g_new0( gfloat* , 12 );
00310 values[0] = g_new0( gfloat , 12*31 );
00311 flags = g_new0( char* , 12 );
00312 flags[0] = g_new0( char , 12*31 );
00313
00314 for ( i=1 ; i<12 ; i++ )
00315 {
00316 flags[i] = flags[i-1]+31;
00317 values[i] = values[i-1]+31;
00318 }
00319
00320 fread( station_number , sizeof(char) , 7 , fp );
00321 fread( ¶meter , sizeof(gint8) , 1 , fp );
00322 fread( &year , sizeof(gint16) , 1 , fp );
00323 fread( values[0] , sizeof(gfloat) , 12*31 , fp );
00324 fread( flags[0] , sizeof(char) , 12*31 , fp );
00325
00326 if ( byte_order != G_BYTE_ORDER )
00327 {
00328 year = GINT16_FROM_LE(year);
00329 for ( i=0 ; i<12 ; i++ )
00330 for ( j=0 ; j<31 ; j++ )
00331 values[i][j] = gfloat_from_le(values[i][j]);
00332 }
00333
00334 g_memmove(rec->staname,station_number,7);
00335 rec->year = year;
00336 rec->parameter = parameter;
00337 for ( i=0 ; i<12 ; i++ )
00338 for ( j=0 ; j<31 ; j++ )
00339 rec->flows[i][j] = values[i][j];
00340
00341 g_free( values[0] );
00342 g_free( values );
00343 g_free( flags[0] );
00344 g_free( flags );
00345 g_free( station_number );
00346
00347 return 0;
00348 }