00001 #include <stdio.h>
00002 #include <glib.h>
00003
00004 #include "utils/utils.h"
00005 #include "sed_hydrotrend.h"
00006
00007
00008 GQuark
00009 sed_hydrotrend_error_quark( void )
00010 {
00011 return g_quark_from_static_string( "sed-hydrorend-error-quark" );
00012 }
00013
00014
00021 Sed_hydrotrend_header*
00022 sed_hydrotrend_read_header( FILE *fp )
00023 {
00024 return sed_hydrotrend_read_header_from_byte_order( fp , G_BYTE_ORDER );
00025 }
00026
00034 Sed_hydrotrend_header*
00035 sed_hydrotrend_read_header_from_byte_order( FILE *fp , gint order )
00036 {
00037 Sed_hydrotrend_header *hdr = NULL;
00038
00039 if ( fp )
00040 {
00041 gint n;
00042 size_t (*fread_int)(void*,size_t,size_t,FILE*);
00043
00044 if ( order==G_BYTE_ORDER ) fread_int = fread;
00045 else fread_int = eh_fread_int32_swap;
00046
00047 if ( fread_int( &n , sizeof(gint32) , 1 , fp )==1 && (n>=0 && n<2048 ) )
00048 {
00049 gchar* str = eh_new( gchar , n+1 );
00050
00051 hdr = eh_new( Sed_hydrotrend_header , 1 );
00052
00053 fread( str , sizeof(gchar) , n , fp );
00054 str[n] = '\0';
00055
00056 hdr->comment = g_strescape( str , "\\" );
00057 eh_free( str );
00058
00059 if ( fread_int( &(hdr->n_grains ) , sizeof(gint) , 1 , fp )!=1 || hdr->n_grains <=0
00060 || fread_int( &(hdr->n_seasons) , sizeof(gint) , 1 , fp )!=1 || hdr->n_seasons<=0
00061 || fread_int( &(hdr->n_samples) , sizeof(gint) , 1 , fp )!=1 || hdr->n_samples<=0 )
00062 {
00063 hdr = sed_hydrotrend_header_destroy( hdr );
00064 }
00065 }
00066
00067 if ( !hdr )
00068 {
00069 eh_debug( "Trouble reading hydrotrend header." );
00070 eh_debug( "Is the byte of the hydrotrend file the same as that" );
00071 eh_debug( "on the machine you are running sedflux?" );
00072 eh_debug( "The byte order of your system is %s" ,
00073 (G_BYTE_ORDER==G_BIG_ENDIAN)?"big-endian":"little-endian" );
00074 }
00075 }
00076
00077 return hdr;
00078 }
00079
00080 Sed_hydrotrend_header*
00081 sed_hydrotrend_join_header_from_byte_order( FILE** fp_list , gint order , GError** err )
00082 {
00083 Sed_hydrotrend_header *hdr = NULL;
00084
00085 eh_return_val_if_fail( err==NULL || *err==NULL , NULL );
00086
00087 if ( fp_list && *fp_list )
00088 {
00089 FILE** fp;
00090 Sed_hydrotrend_header* h;
00091 GError* tmp_err = NULL;
00092
00093 hdr = sed_hydrotrend_read_header_from_byte_order( fp_list[0] , order );
00094 rewind( fp_list[0] );
00095
00096 for ( fp=fp_list+1 ; *fp && !tmp_err ; fp++ )
00097 {
00098 h = sed_hydrotrend_read_header_from_byte_order( *fp , order );
00099 rewind( *fp );
00100
00101 if ( h )
00102 {
00103 if ( h->n_grains != hdr->n_grains && !tmp_err )
00104 g_set_error( &tmp_err , SED_HYDROTREND_ERROR , SED_HYDROTREND_ERROR_BAD_HEADER ,
00105 "Number of grain sizes in Hydrotrend files do not match (%d!=%d)" , hdr->n_grains , h->n_grains );
00106 if ( h->n_seasons != hdr->n_seasons && !tmp_err )
00107 g_set_error( &tmp_err , SED_HYDROTREND_ERROR , SED_HYDROTREND_ERROR_BAD_HEADER ,
00108 "Number of seasons in Hydrotrend files do not match (%d!=%d)" , hdr->n_seasons , h->n_seasons );
00109
00110 if ( !tmp_err )
00111 {
00112
00113 gchar* tmp_str = hdr->comment;
00114
00115 hdr->comment = g_strjoin( ";" , tmp_str , h->comment , NULL );
00116 hdr->n_samples += h->n_samples;
00117
00118 eh_free( tmp_str );
00119 }
00120
00121 eh_free( h->comment );
00122 eh_free( h );
00123 }
00124 }
00125
00126 if ( tmp_err )
00127 {
00128 g_propagate_error( err , tmp_err );
00129 eh_free( hdr->comment );
00130 eh_free( hdr );
00131 hdr = NULL;
00132 }
00133 }
00134
00135 return hdr;
00136 }
00137
00138 Sed_hydrotrend_header*
00139 sed_hydrotrend_header_destroy( Sed_hydrotrend_header* h )
00140 {
00141 if ( h )
00142 {
00143 if ( h->comment ) eh_free( h->comment );
00144 eh_free( h );
00145 }
00146 return NULL;
00147 }
00148
00149 gssize
00150 sed_hydrotrend_write_header_to_byte_order( FILE* fp ,
00151 gint n_grains ,
00152 gint n_seasons ,
00153 gint n_samples ,
00154 gchar* comment_s ,
00155 gint order )
00156 {
00157 gssize n = 0;
00158
00159 if ( fp )
00160 {
00161 gint len;
00162 gssize (*fwrite_int)(void*,size_t,size_t,FILE*);
00163
00164 if ( !comment_s )
00165 comment_s = g_strdup( "No comment" );
00166
00167 len = strlen( comment_s );
00168
00169 if ( order==G_BYTE_ORDER ) fwrite_int = fwrite;
00170 else fwrite_int = eh_fwrite_int32_swap;
00171
00172 n += fwrite_int( &len , sizeof(int) , 1 , fp );
00173 n += fwrite ( comment_s , sizeof(char) , len , fp );
00174
00175 n += fwrite_int( &n_grains , sizeof(int) , 1 , fp );
00176 n += fwrite_int( &n_seasons , sizeof(int) , 1 , fp );
00177 n += fwrite_int( &n_samples , sizeof(int) , 1 , fp );
00178 }
00179
00180 return n;
00181 }
00182
00193 gssize
00194 sed_hydrotrend_write_header( FILE* fp ,
00195 gint n_grains ,
00196 gint n_seasons ,
00197 gint n_samples ,
00198 gchar* comment_s )
00199 {
00200 gssize n = 0;
00201
00202 if ( fp )
00203 {
00204 gint len;
00205
00206 if ( !comment_s )
00207 comment_s = g_strdup( "No comment" );
00208
00209 len = strlen( comment_s );
00210
00211 n += fwrite( &len , sizeof(int) , 1 , fp );
00212 n += fwrite( comment_s , sizeof(char) , len , fp );
00213
00214 n += fwrite( &n_grains , sizeof(int) , 1 , fp );
00215 n += fwrite( &n_seasons , sizeof(int) , 1 , fp );
00216 n += fwrite( &n_samples , sizeof(int) , 1 , fp );
00217 }
00218
00219 return n;
00220 }
00221
00222 gint
00223 sed_hydrotrend_byte_order( const gchar* file , GError** error )
00224 {
00225 gint order = 0;
00226
00227 eh_require( error==NULL || *error==NULL );
00228
00229 if ( file )
00230 {
00231 GError* tmp_err = NULL;
00232 FILE* fp = eh_fopen_error( file , "r" , &tmp_err );
00233
00234 if ( !tmp_err )
00235 {
00236 Sed_hydrotrend_header* h = NULL;
00237
00238 h = sed_hydrotrend_read_header_from_byte_order( fp , G_BIG_ENDIAN );
00239 if ( h )
00240 order = G_BIG_ENDIAN;
00241 else
00242 {
00243 rewind( fp );
00244 h = sed_hydrotrend_read_header_from_byte_order( fp , G_LITTLE_ENDIAN );
00245 order = G_LITTLE_ENDIAN;
00246 }
00247
00248 if ( h )
00249 {
00250 eh_free( h->comment );
00251 eh_free( h );
00252 }
00253
00254 fclose( fp );
00255 }
00256 }
00257
00258 return order;
00259 }
00260
00261 gint
00262 sed_hydrotrend_guess_byte_order( FILE* fp )
00263 {
00264 gint byte_order = -1;
00265
00266 if ( fp )
00267 {
00268 gint n;
00269 fread( &n , sizeof(gint) , 1 , fp );
00270
00271 if ( n>=0 || n<2048 )
00272 byte_order = G_BYTE_ORDER;
00273 else
00274 {
00275 rewind( fp );
00276 eh_fread_int32_swap( &n , sizeof(gint) , 1 , fp );
00277
00278 if ( n>=0 || n<2048 )
00279 {
00280 if ( G_BYTE_ORDER==G_BIG_ENDIAN ) byte_order = G_LITTLE_ENDIAN;
00281 else byte_order = G_BIG_ENDIAN;
00282 }
00283 }
00284
00285 rewind( fp );
00286 }
00287
00288 return byte_order;
00289 }
00290
00298 Sed_hydro
00299 sed_hydrotrend_read_next_rec( FILE* fp , int n_grains )
00300 {
00301 return sed_hydrotrend_read_next_rec_from_byte_order( fp , n_grains , G_BYTE_ORDER );
00302 }
00303
00304
00313 Sed_hydro
00314 sed_hydrotrend_read_next_rec_from_byte_order( FILE *fp , int n_grains , gint order )
00315 {
00316 int n;
00317 float* fval = eh_new( float , 4+n_grains );
00318 Sed_hydro rec = NULL;
00319
00320 if ( order==G_BYTE_ORDER ) n = fread ( fval , sizeof(float) , 4+n_grains , fp );
00321 else n = eh_fread_flt_swap( fval , sizeof(float) , 4+n_grains , fp );
00322
00323 if ( n==4+n_grains )
00324 {
00325 gint i;
00326
00327 rec = sed_hydro_new( n_grains );
00328
00329 sed_hydro_set_velocity( rec , fval[0] );
00330 sed_hydro_set_width ( rec , fval[1] );
00331 sed_hydro_set_depth ( rec , fval[2] );
00332 sed_hydro_set_bedload ( rec , fval[3] );
00333
00334 for (i=0 ; i<n_grains ; i++)
00335 sed_hydro_set_nth_concentration( rec , i , fval[i+4] );
00336 }
00337 eh_free( fval );
00338
00339 return rec;
00340 }
00341
00352 Sed_hydro*
00353 sed_hydrotrend_read_recs( FILE* fp , gint rec_0 , gint n_recs , gint byte_order , GError** error )
00354 {
00355 Sed_hydro* rec_a = NULL;
00356
00357 eh_require( rec_0 >= 0 );
00358
00359 eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00360
00361 if ( fp || n_recs!=0 )
00362 {
00363 gint n;
00364 gint last = sed_hydrotrend_fseek( fp , 0 , SEEK_END , byte_order );
00365 gint cur = sed_hydrotrend_fseek( fp , rec_0 , SEEK_SET , byte_order );
00366 gint n_grains = sed_hydrotrend_n_grains( fp , byte_order , NULL );
00367
00368 if ( last-cur < n_recs || n_recs<0 )
00369 n_recs = last - cur;
00370
00371 rec_a = eh_new( Sed_hydro , n_recs+1 );
00372
00373 for ( n=0 ; n<n_recs ; n++ )
00374 rec_a[n] = sed_hydrotrend_read_next_rec_from_byte_order( fp , n_grains , byte_order );
00375 rec_a[n] = NULL;
00376 }
00377
00378 return rec_a;
00379 }
00380
00388 gssize
00389 sed_hydrotrend_write_record( FILE *fp , Sed_hydro rec )
00390 {
00391 return sed_hydrotrend_write_record_to_byte_order( fp , rec , G_BYTE_ORDER );
00392 }
00393
00402 gssize
00403 sed_hydrotrend_write_record_to_byte_order( FILE *fp , Sed_hydro rec , gint order )
00404 {
00405 gssize n;
00406
00407 if ( rec )
00408 {
00409 gint i;
00410 gint n_grains = sed_hydro_size( rec );
00411 float* fval = eh_new( float , 4+n_grains );
00412
00413 fval[0] = sed_hydro_velocity( rec );
00414 fval[1] = sed_hydro_width ( rec );
00415 fval[2] = sed_hydro_depth ( rec );
00416 fval[3] = sed_hydro_bedload ( rec );
00417
00418 for (i=0 ; i<n_grains ; i++)
00419 fval[4+i] = sed_hydro_nth_concentration( rec , i );
00420
00421 if ( order==G_BYTE_ORDER )
00422 n = fwrite ( fval , sizeof(float) , 4+n_grains , fp );
00423 else
00424 n = eh_fwrite_flt_swap( fval , sizeof(float) , 4+n_grains , fp );
00425
00426 eh_free( fval );
00427 }
00428
00429 return n;
00430 }
00431
00441 gssize
00442 sed_hydrotrend_read_next_n_recs( FILE* fp , Sed_hydro* rec , int n_grains , int n_recs )
00443 {
00444 gssize n = 0;
00445
00446 do
00447 {
00448 rec[n] = sed_hydrotrend_read_next_rec( fp , n_grains );
00449 }
00450 while ( rec[n] && (++n)<n_recs );
00451
00452 return n;
00453 }
00454
00455 Sed_hydro*
00456 sed_hydrotrend_read( const gchar* file , gint byte_order , int* n_seasons , GError** error )
00457 {
00458 return sed_hydrotrend_read_n_recs( file , -1 , byte_order , n_seasons , error );
00459 }
00460
00461 Sed_hydro*
00462 sed_hydrotrend_read_n_recs( const gchar* file , gint n_recs , gint byte_order , int* n_seasons , GError** error )
00463 {
00464 Sed_hydro* arr = NULL;
00465
00466 eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00467
00468 if ( file && n_recs!=0 )
00469 {
00470 GError* err = NULL;
00471 FILE* fp = eh_fopen_error( file , "r" , &err );
00472
00473 if ( !err )
00474 {
00475 Sed_hydrotrend_header* h = NULL;
00476
00477 h = sed_hydrotrend_read_header_from_byte_order( fp , byte_order );
00478
00479 if ( h )
00480 {
00481 if ( n_recs<0 ) n_recs = h->n_samples;
00482 else if ( n_recs>h->n_samples ) n_recs = h->n_samples;
00483
00484 arr = sed_hydrotrend_read_recs( fp , 0 , n_recs , byte_order , &err );
00485
00486 if ( n_seasons ) *n_seasons = h->n_seasons;
00487
00488 if ( !err )
00489 {
00490 gint n_read = g_strv_length( (gchar**)arr );
00491
00492 if ( n_read != n_recs )
00493 {
00494 eh_warning( "Number of items read does not match number of items in header" );
00495 eh_debug( "Number of items in header : %d" , h->n_samples );
00496 eh_debug( "Number of items read : %d" , n_read );
00497 }
00498 }
00499 else
00500 g_propagate_error( error , err );
00501
00502 eh_free( h->comment );
00503 eh_free( h );
00504 }
00505 }
00506 else
00507 g_propagate_error( error , err );
00508 }
00509
00510 return arr;
00511 }
00512
00523 gssize
00524 sed_hydrotrend_write( gchar* file , Sed_hydro* rec_a , gint n_seasons , gchar* comment_s , GError** error )
00525 {
00526 gssize n = 0;
00527
00528 eh_return_val_if_fail( error==NULL || *error==NULL , 0 );
00529 eh_require( n_seasons>0 );
00530
00531 if ( file && rec_a && *rec_a )
00532 {
00533 GError* err = NULL;
00534 FILE* fp = eh_fopen_error( file , "w" , &err );
00535 gint n_samples = g_strv_length( (gchar**)rec_a );
00536 gint n_grains = sed_hydro_size(rec_a[0]);
00537
00538 if ( !err )
00539 {
00540 sed_hydrotrend_write_header( fp , n_grains , n_seasons , n_samples , comment_s );
00541 sed_hydro_array_write_hydrotrend_records( fp , rec_a );
00542 }
00543 else
00544 {
00545 g_propagate_error( error , err );
00546 n = 0;
00547 }
00548 }
00549
00550 return n;
00551 }
00552
00553 gssize
00554 sed_hydro_array_write_hydrotrend_records_to_byte_order( FILE* fp , Sed_hydro* rec_a , gint order )
00555 {
00556 gssize n = 0;
00557
00558 if ( fp && rec_a )
00559 {
00560 Sed_hydro* rec;
00561
00562 for ( rec=rec_a ; *rec ; rec++ )
00563 sed_hydrotrend_write_record_to_byte_order( fp , *rec , order );
00564 }
00565
00566 return n;
00567 }
00568
00576 gssize
00577 sed_hydro_array_write_hydrotrend_records( FILE* fp , Sed_hydro* rec_a )
00578 {
00579 return sed_hydro_array_write_hydrotrend_records_to_byte_order( fp , rec_a , G_BYTE_ORDER );
00580 }
00581
00608 gint
00609 sed_hydrotrend_fseek( FILE* fp , gint offset , gint whence , gint byte_order )
00610 {
00611 gint pos = -1;
00612
00613 if ( fp )
00614 {
00615 gint rec_size = sed_hydrotrend_record_size( fp , byte_order , NULL );
00616 gint data_start = sed_hydrotrend_data_start ( fp , byte_order , NULL );
00617
00618 if ( whence == SEEK_SET )
00619 fseek( fp , rec_size*offset + data_start , SEEK_SET );
00620 else
00621 fseek( fp , rec_size*offset , whence );
00622
00623 pos = ( ftell( fp ) - data_start ) / rec_size ;
00624 }
00625
00626 return pos;
00627 }
00628
00637 gint
00638 sed_hydrotrend_record_size( FILE* fp , gint byte_order , Sed_hydrotrend_header* h )
00639 {
00640 gint n = 0;
00641
00642 if ( fp )
00643 {
00644 if ( h )
00645 n = ( h->n_grains + 4 )*sizeof(float);
00646 else
00647 {
00648 gint where = ftell( fp );
00649
00650 rewind( fp );
00651
00652 h = sed_hydrotrend_read_header_from_byte_order( fp , byte_order );
00653
00654 eh_require( h );
00655
00656 n = ( h->n_grains + 4 )*sizeof(float);
00657
00658 fseek( fp , where , SEEK_SET );
00659
00660 eh_free( h->comment );
00661 eh_free( h );
00662 }
00663 }
00664
00665 return n;
00666 }
00667
00676 gint
00677 sed_hydrotrend_n_grains( FILE* fp , gint byte_order , Sed_hydrotrend_header* h )
00678 {
00679 gint n = 0;
00680
00681 if ( fp )
00682 {
00683 if ( h )
00684 n = h->n_grains;
00685 else
00686 {
00687 gint where = ftell( fp );
00688
00689 rewind( fp );
00690
00691 h = sed_hydrotrend_read_header_from_byte_order( fp , byte_order );
00692
00693 eh_require( h );
00694
00695 n = h->n_grains;
00696
00697 fseek( fp , where , SEEK_SET );
00698
00699 eh_free( h->comment );
00700 eh_free( h );
00701 }
00702 }
00703
00704 return n;
00705 }
00706
00716 gint
00717 sed_hydrotrend_data_start( FILE* fp , gint byte_order , Sed_hydrotrend_header* h )
00718 {
00719 gint n = 0;
00720
00721 if ( fp )
00722 {
00723 if ( h )
00724 n = sizeof(gint) + strlen(h->comment) + 3*sizeof(gint);
00725 else
00726 {
00727 gint where = ftell( fp );
00728
00729 rewind( fp );
00730
00731 h = sed_hydrotrend_read_header_from_byte_order( fp , byte_order );
00732
00733 eh_require( h );
00734
00735 n = ftell( fp );
00736
00737 fseek( fp , where , SEEK_SET );
00738
00739 eh_free( h->comment );
00740 eh_free( h );
00741 }
00742 }
00743
00744 return n;
00745 }
00746