/Users/huttone/Devel/sedflux-new/sedflux/trunk/ew/sedutils/read_usgs.c

Go to the documentation of this file.
00001 //---
00002 //
00003 // This file is part of sedflux.
00004 //
00005 // sedflux is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // sedflux is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with sedflux; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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; // a doubly-linked list of daily_val_st-s
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 // read in the data.
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 //      data_array = g_array_new( FALSE , FALSE , sizeof(double) );
00199       new_rec = g_new0( daily_val_st , 1 );
00200 
00201 // read one record (one year of daily values)
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 // break out of the loop if EOF was encountered.
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 // add the daily values to the data file.
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 //      eh_add_data_record_row( data , data_array );
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 // add the data to a Eh_data_record.
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 // write the data.
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( &parameter     , 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 }

Generated on Fri Jan 4 18:04:16 2008 for sedflux by  doxygen 1.5.2