00001
00002 #define IFM_VERSION "version 3.3a (March 22, 2005)"
00003
00004 static char g_history[] =
00005 "----------------------------------------------------------------------\n"
00006 " history:\n"
00007 "\n"
00008 " 1.0 November 21, 2002\n"
00009 " - initial release\n"
00010 "\n"
00011 " 1.1 November 27, 2002\n"
00012 " - renamed from Hfile to Imon (I-file monitor)\n"
00013 "\n"
00014 " 1.2 November 27, 2002\n"
00015 " - after N idle mid-run TRs, print warning message\n"
00016 " - added '-nice INCR' option\n"
00017 " - added BEEP on error\n"
00018 " - replaced '-status' with '-quiet', so '-debug 1' is default\n"
00019 " - no fatal error during volume search, try to recover\n"
00020 " - display that the user should use <ctrl-c> to quit\n"
00021 " - adjust globbing to be '...[0-9][02468]?/I.*' (or w/[13579])\n"
00022 "\n"
00023 " 1.3 December 13, 2002\n"
00024 " - compile as standalone (include mcw_glob, but not mcw_malloc)\n"
00025 " - added l_THD_filesize (local copy of THD_filesize)\n"
00026 " - removed dependance on mrilib.h and r_idisp.h\n"
00027 "\n"
00028 " 2.0 January 15, 2003\n"
00029 " - rtfeedme feature\n"
00030 " o added -rt option: pass data to afni as collected\n"
00031 " o added -host option: specify afni host for real-time\n"
00032 " o added -swap option: byte swap pairs before sending to afni\n"
00033 " o created realtime.[ch] for all RT processing functions\n"
00034 " o (see gAC struct and ART_ functions)\n"
00035 " - actually read and store images (to be sent to afni)\n"
00036 " - moved function declarations to Imon.c (from Imon.h)\n"
00037 "\n"
00038 " 2.1 January 27, 2003\n"
00039 " - added '-nt VOLUMES_PER_RUN' option (for checking stalled runs)\n"
00040 "\n"
00041 " 2.2 February 2, 2003\n"
00042 " - allow IFM_MAX_GE_FAILURES file reading failures\n"
00043 "\n"
00044 " 2.3 February 14, 2003\n"
00045 " - added -start_file option\n"
00046 " - created opts_t struct for user options\n"
00047 "\n"
00048 " 2.4 February 18, 2003\n"
00049 " - added DRIVE_AFNI command to open a graph window\n"
00050 " - added -drive_afni option\n"
00051 " - added NOTE command to append Imon command to any new dataset\n"
00052 "\n"
00053 " 2.5 February 20, 2003\n"
00054 " - deal better with missing first slice of first volume\n"
00055 " - make each DRIVE_AFNI command separate\n"
00056 "\n"
00057 " 2.6 March 25, 2003\n"
00058 " - added -GERT_Reco2 option\n"
00059 " - RT: only send good volumes to afni\n"
00060 " - RT: added -rev_byte_order option\n"
00061 " - RT: also open relevant image window\n"
00062 " - RT: mention starting file in NOTE command\n"
00063 "\n"
00064 " 2.7 June 25, 2003\n"
00065 " - added axes offsets (see xorg and realtime.c: XYZFIRST)\n"
00066 "\n"
00067 " 2.8 June 27, 2003\n"
00068 " - BYTEORDER is now operational in plug_realtime\n"
00069 " - implemented -rev_byte_order option\n"
00070 "\n"
00071 " 2.9 July 27, 2003\n"
00072 " - wrap unknown printed strings in NULL check\n"
00073 " - only print newer files in debug check\n"
00074 "\n"
00075 " 2.10 August 5, 2003\n"
00076 " - added '-sp SLICE_PATTERN' option (see spat and opts.sp)\n"
00077 "\n"
00078 " 2.11 August 14, 2003\n"
00079 " - added '-quit' option\n"
00080 " - changed CHECK_NULL_STR() output to (NULL) (to see when used)\n"
00081 " - change exit status to 0 (why the heck did I use 1?)\n"
00082 " - allow I.* or i.* filename expansions\n"
00083 "\n"
00084 " 3.0 August 20, 2003\n"
00085 " - It seems that the GE scanners may write the files for a volume\n"
00086 " out of order. To handle that possibility, volume_match() will\n"
00087 " re-test any volume for error conditions (separated by sleep()).\n"
00088 " Errors will be reported only if they persist (i.e. the scanner\n"
00089 " is not still working on the volume).\n"
00090 "\n"
00091 " 3.1 September 02, 2003\n"
00092 " - Add option '-od OUTPUT_DIRECTORY' for the GERT_Reco2 case.\n"
00093 "\n"
00094 " 3.2 January 13, 2004\n"
00095 " - added '-zorder ORDER' option to specify slice timing in the\n"
00096 " real-time mode (the real-time default is now 'alt')\n"
00097 " - added '-hist' option for history display\n"
00098 "\n"
00099 " 3.3 February 13, 2004\n"
00100 " - added '-rt_cmd' option for passing commands to the realtime plugin\n"
00101 " (this option may be used multiple times)\n"
00102 " - '-drive_cmd' option can now be used multiple times\n"
00103 " - realtime.c: changed default zorder back to seq\n"
00104 " (affects slice order in the RT plugin)\n"
00105 " - realtime.c: passed list of drive and rt commands to RT plugin\n"
00106 " - added add_to_string_list() and empty_string_list()\n"
00107 "\n"
00108 " 3.3a March 22, 2005 - removed all tabs\n"
00109 " 3.3b May 16, 2005 - incorporate some Dimon changes\n"
00110 " 3.4 July 5, 2005 - removed tabs\n"
00111 "----------------------------------------------------------------------\n";
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 #include <stdio.h>
00150 #include <ctype.h>
00151 #include <dirent.h>
00152 #include <errno.h>
00153 #include <math.h>
00154 #include <signal.h>
00155 #include <stdlib.h>
00156 #include <string.h>
00157 #include <sys/types.h>
00158 #include <sys/stat.h>
00159 #include <unistd.h>
00160
00161 #include "Imon.h"
00162 #include "l_mcw_glob.h"
00163 #include "thd_iochan.h"
00164 #include "realtime.h"
00165
00166 #define IFM_PROG_NAME "Imon"
00167
00168
00169
00170
00171 static int add_to_string_list ( string_list * list, char * str );
00172 static int alloc_x_im ( im_store_t * is, int bytes );
00173 static int check_error ( int * retry, float tr, char * note );
00174 static int check_im_byte_order ( int * order, vol_t * v, param_t * p );
00175 static int check_im_store_space( im_store_t * is, int num_images );
00176 static int check_stalled_run ( int run, int seq_num, int naps, int nap_time );
00177 static int complete_orients_str( vol_t * v, param_t * p );
00178 static int create_gert_script ( stats_t * s, opts_t * opts );
00179 static int dir_expansion_form ( char * sin, char ** sexp );
00180 static int empty_string_list ( string_list * list, int free_mem );
00181 static int find_first_volume ( vol_t * v, param_t * p, ART_comm * ac );
00182 static int find_fl_file_index ( param_t * p, char * file );
00183 static int find_more_volumes ( vol_t * v, param_t * p, ART_comm * ac );
00184 static int find_next_zoff ( param_t * p, int start, float zoff );
00185 static int init_extras ( param_t * p, ART_comm * ac );
00186 static int init_options ( param_t * p, ART_comm * a, int argc,
00187 char * argv[] );
00188 static int nap_time_from_tr ( float tr );
00189 static int path_to_dir_n_suffix( char * dir, char * suff, char * path );
00190 static int read_ge_files ( param_t * p, int start, int max );
00191 static int read_ge_image ( char * pathname, finfo_t * fp,
00192 int get_image, int need_memory );
00193 static int scan_ge_files ( param_t * p, int next, int nfiles );
00194 static int set_nice_level ( int level );
00195 static int set_volume_stats ( param_t * p, stats_t * s, vol_t * v );
00196 static int show_run_stats ( stats_t * s );
00197 static int str_char_count ( char * str, int len, char target );
00198 static int swap_4 ( void * ptr );
00199
00200 static void hf_signal ( int signum );
00201
00202
00203 static int volume_match ( vol_t * vin, vol_t * vout, param_t * p, int start );
00204 static int volume_search ( vol_t * V, param_t * p, int start, int maxsl,
00205 int * fl_start );
00206
00207
00208 static int idisp_hf_opts_t ( char * info, opts_t * opt );
00209 static int idisp_hf_param_t ( char * info, param_t * p );
00210 static int idisp_hf_vol_t ( char * info, vol_t * v );
00211 static int idisp_ge_extras ( char * info, ge_extras * E );
00212 static int idisp_ge_header_info ( char * info, ge_header_info * I );
00213 static int idisp_im_store_t ( char * info, im_store_t * is );
00214
00215 static int usage ( char * prog, int level );
00216
00217
00218 static unsigned long l_THD_filesize( char * pathname );
00219
00220
00221
00222 #define MAIN
00223
00224
00225
00226
00227 IFM_debug gD;
00228 param_t gP;
00229 stats_t gS;
00230 ART_comm gAC;
00231
00232
00233 int main( int argc, char * argv[] )
00234 {
00235 ART_comm * ac = &gAC;
00236 param_t * p = &gP;
00237 vol_t baseV;
00238 int ret_val;
00239
00240
00241 if ( (ret_val = init_options( p, ac, argc, argv )) != 0 )
00242 return ret_val;
00243
00244 if ( (ret_val = init_extras( p, ac )) != 0 )
00245 return ret_val;
00246
00247 if ( (ret_val = find_first_volume( &baseV, p, ac )) != 0 )
00248 return ret_val;
00249
00250 if ( (ret_val = find_more_volumes( &baseV, p, ac )) != 0 )
00251 return ret_val;
00252
00253 return 0;
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 static int find_first_volume( vol_t * v, param_t * p, ART_comm * ac )
00268 {
00269 int max_im_alloc = IFM_MAX_IM_ALLOC;
00270 int ret_val;
00271 int fl_start = 0;
00272
00273 if ( gD.level > 0 )
00274 fprintf( stderr, "-- scanning for first volume\n" );
00275
00276 ret_val = 0;
00277 while ( ret_val == 0 )
00278 {
00279 ret_val = read_ge_files( p, fl_start, max_im_alloc );
00280
00281 if ( ret_val > 0 )
00282 {
00283 ret_val = volume_search( v, p, 0, 0, &fl_start );
00284
00285 if ( ret_val == -1 )
00286 ret_val = 0;
00287
00288 if ( (ret_val == 0) && (p->nused > (max_im_alloc / 2)) )
00289 {
00290
00291
00292
00293
00294
00295 max_im_alloc *= 2;
00296 }
00297 }
00298
00299 if ( ret_val == 0 )
00300 {
00301 if ( gD.level > 0 )
00302 fprintf( stderr, "." );
00303
00304 sleep( 4 );
00305 }
00306 else if ( ret_val > 0 )
00307 {
00308 if ( gD.level > 0 )
00309 {
00310 fprintf( stderr, "\n-- first volume found\n" );
00311 if ( gD.level > 1 )
00312 {
00313 idisp_hf_vol_t( "first volume : ", v );
00314 idisp_hf_param_t( "first vol - new params : ", p );
00315 }
00316 }
00317
00318
00319 if ( p->nalloc < (4 * v->nim) )
00320 {
00321 p->nalloc = 4 * v->nim;
00322 p->flist = (finfo_t *)realloc( p->flist,
00323 p->nalloc*sizeof(finfo_t) );
00324 if ( p->flist == NULL )
00325 {
00326 fprintf( stderr, "** FFV: failure to allocate %d finfo_t "
00327 "structs!\n", p->nalloc );
00328 return -1;
00329 }
00330
00331 if ( gD.level > 1 )
00332 idisp_hf_param_t( "++ final realloc of flist : ", p );
00333 }
00334
00335
00336 if ( complete_orients_str( v, p ) < 0 )
00337 return -1;
00338
00339
00340 if ( check_im_byte_order( &ac->byte_order, v, p ) < 0 )
00341 return -1;
00342
00343
00344 if ( ac->state == ART_STATE_TO_OPEN )
00345 ART_open_afni_link( ac, 5, 0, gD.level );
00346
00347 if ( ac->state == ART_STATE_TO_SEND_CTRL )
00348 ART_send_control_info( ac, v, gD.level );
00349
00350 if ( ac->state == ART_STATE_IN_USE )
00351 ART_send_volume( ac, v, gD.level );
00352
00353 if ( gD.level > 1 )
00354 {
00355 ART_idisp_ART_comm( "-- first vol ", ac );
00356 idisp_im_store_t( "-- first vol ", &p->im_store );
00357 }
00358 }
00359 else
00360 return ret_val;
00361 }
00362
00363 if ( ret_val > 0 )
00364 return 0;
00365 else
00366 return ret_val;
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 static int find_more_volumes( vol_t * v0, param_t * p, ART_comm * ac )
00380 {
00381 vol_t vn;
00382 int ret_val, done;
00383 int run, seq_num, next_im;
00384 int fl_index;
00385 int naps;
00386 int nap_time;
00387
00388 if ( v0 == NULL || p == NULL )
00389 {
00390 fprintf( stderr, "error: IFM:FMV() lacking parameters\n" );
00391 return -1;
00392 }
00393
00394 done = 0;
00395 naps = 0;
00396
00397 run = v0->run;
00398 seq_num = v0->seq_num = 1;
00399 fl_index = v0->fn_n + 1;
00400 next_im = v0->fn_n + 1;
00401
00402 nap_time = nap_time_from_tr( v0->geh.tr );
00403
00404 if ( gD.level > 0 )
00405 {
00406 fprintf( stderr, "-- scanning for additional volumes...\n" );
00407 fprintf( stderr, "-- run %d: %d ", run, seq_num );
00408 }
00409
00410
00411 signal( SIGTERM, hf_signal );
00412 signal( SIGINT, hf_signal );
00413
00414 if ( set_volume_stats( p, &gS, v0 ) )
00415 return -1;
00416
00417 while ( ! done )
00418 {
00419
00420 ret_val = 1;
00421 while ( (ret_val == 1) || (ret_val == -1) )
00422 {
00423 ret_val = volume_match( v0, &vn, p, fl_index );
00424
00425 if ( ret_val < -1 )
00426 return ret_val;
00427
00428 if ( (ret_val == 1) || (ret_val == -1) )
00429 {
00430 if ( gD.level > 2 )
00431 idisp_hf_vol_t( "-- new volume: ", &vn );
00432
00433 fl_index += vn.nim;
00434 next_im = vn.fn_n + 1;
00435
00436 if ( vn.run != run )
00437 {
00438
00439 if ( ac->state == ART_STATE_IN_USE )
00440 ART_send_end_of_run( ac, run, seq_num, gD.level );
00441
00442 run = vn.run;
00443 seq_num = 1;
00444
00445 if ( gD.level > 0 )
00446 fprintf( stderr, "\n-- run %d: %d ", run, seq_num );
00447 }
00448 else
00449 {
00450 seq_num++;
00451
00452 if ( gD.level > 0 )
00453 fprintf( stderr, "%d ", seq_num );
00454 }
00455
00456 vn.seq_num = seq_num;
00457
00458 if ( set_volume_stats( p, &gS, &vn ) )
00459 return -1;
00460
00461 if ( complete_orients_str( &vn, p ) < 0 )
00462 return -1;
00463
00464 if ( ac->state == ART_STATE_TO_SEND_CTRL )
00465 ART_send_control_info( ac, &vn, gD.level );
00466
00467
00468 if ( (ac->state == ART_STATE_IN_USE) && (ret_val == 1) )
00469 ART_send_volume( ac, &vn, gD.level );
00470
00471 naps = 0;
00472 }
00473 }
00474
00475
00476
00477 ret_val = read_ge_files( p, next_im, p->nalloc );
00478 fl_index = 0;
00479
00480 while ( (ret_val >= 0 ) &&
00481 (ret_val < v0->nim) )
00482 {
00483 if ( naps > 0 )
00484 {
00485 if ( p->opts.quit )
00486 {
00487 if ( ac->state == ART_STATE_IN_USE )
00488 ART_send_end_of_run( ac, run, seq_num, gD.level );
00489
00490 show_run_stats( &gS );
00491 return 0;
00492 }
00493
00494
00495 if ( check_stalled_run( run, seq_num, naps, nap_time ) > 0 )
00496 if ( ac->state == ART_STATE_IN_USE )
00497 ART_send_end_of_run( ac, run, seq_num, gD.level );
00498
00499 if ( gD.level > 0 )
00500 fprintf( stderr, ". " );
00501 }
00502
00503 sleep( nap_time );
00504 naps ++;
00505
00506 ret_val = read_ge_files( p, next_im, p->nalloc );
00507 }
00508
00509 if ( ret_val < 0 )
00510 {
00511 fprintf( stderr, "\n** failure: IFM:RGF fatal error\n" );
00512 return -1;
00513 }
00514 }
00515
00516 return 0;
00517 }
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532 static int volume_search(
00533 vol_t * V,
00534 param_t * p,
00535 int start,
00536 int maxsl,
00537 int * fl_start )
00538 {
00539 finfo_t * fp;
00540 float z_orig, delta, dz, prev_z;
00541 int bound;
00542 int next;
00543 int run0, run1;
00544 int first = start;
00545 int last;
00546
00547 if ( V == NULL || p == NULL || p->flist == NULL || start < 0 )
00548 {
00549 fprintf( stderr, "failure: FNV: bad parameter data\n" );
00550 return -2;
00551 }
00552
00553
00554 if ( (maxsl <= 0) || ((maxsl + first) >= p->nused) )
00555 bound = p->nused;
00556 else
00557 bound = first + maxsl;
00558
00559 if ( (bound - first) < 4 )
00560 return 0;
00561
00562 delta = p->flist[first+1].geh.zoff - p->flist[first].geh.zoff;
00563
00564 run0 = p->flist[first ].geh.uv17;
00565 run1 = p->flist[first+1].geh.uv17;
00566
00567
00568 if ( (fabs(delta) < IFM_EPSILON) || (run1 != run0) )
00569 {
00570 if ( gD.level > 1 )
00571 fprintf( stderr, "-- skipping single slice volume <%s>\n",
00572 p->fnames[p->flist[first].index] );
00573
00574 first++;
00575 delta = p->flist[first+1].geh.zoff - p->flist[first].geh.zoff;
00576 run0 = run1;
00577
00578 if ( fabs(delta) < IFM_EPSILON )
00579 {
00580 fprintf( stderr, "Error: 3 slices with 0 delta, beginning with"
00581 "file <%s>\n", p->fnames[p->flist[start].index] );
00582
00583 *fl_start = p->flist[start+2].index;
00584
00585 return -1;
00586 }
00587 }
00588
00589 fp = p->flist + first;
00590 z_orig = fp->geh.zoff;
00591
00592
00593 fp++;
00594 prev_z = fp->geh.zoff;
00595 run1 = fp->geh.uv17;
00596 dz = delta;
00597
00598
00599 next = first + 2;
00600 while ( (next < bound) && (fabs(dz - delta) < IFM_EPSILON) &&
00601 (run1 == run0) )
00602 {
00603 fp++;
00604
00605 dz = fp->geh.zoff - prev_z;
00606 run1 = fp->geh.uv17;
00607 prev_z = fp->geh.zoff;
00608
00609 next++;
00610 }
00611
00612 last = next - 2;
00613
00614 if ( fabs(fp->geh.zoff - p->flist[first].geh.zoff) < IFM_EPSILON )
00615 {
00616
00617
00618
00619
00620 V->geh = p->flist[first].geh;
00621 V->gex = p->flist[first].gex;
00622 V->nim = last - first + 1;
00623 V->fl_1 = first;
00624 V->fn_1 = p->flist[first].index;
00625 V->fn_n = p->flist[last].index;
00626 strncpy( V->first_file, p->fnames[V->fn_1], IFM_MAX_FLEN );
00627 strncpy( V->last_file, p->fnames[V->fn_n], IFM_MAX_FLEN );
00628 V->z_first = p->flist[first].geh.zoff;
00629 V->z_last = p->flist[last].geh.zoff;
00630 V->z_delta = delta;
00631 V->seq_num = -1;
00632 V->run = V->geh.uv17;
00633
00634 return 1;
00635 }
00636 else if ( (fabs(dz - delta) < IFM_EPSILON) && (run1 == run0) )
00637 return 0;
00638 else if ( dz * delta < 0.0 )
00639 {
00640
00641
00642
00643
00644
00645 fprintf( stderr, "\n"
00646 "*************************************************\n"
00647 "Error: missing slice(s) in first volume!\n"
00648 " attempting to re-start at file: %s\n"
00649 "*************************************************\n",
00650 p->fnames[p->flist[last+1].index] );
00651
00652 *fl_start = p->flist[last+1].index;
00653 }
00654 else
00655 {
00656
00657 int testc;
00658
00659 for ( testc = next - 1; testc < bound; testc++ )
00660 if ( abs( p->flist[first].geh.zoff -
00661 p->flist[testc].geh.zoff ) < IFM_EPSILON )
00662 {
00663
00664
00665 fprintf( stderr, "\n"
00666 "*************************************************\n"
00667 "Error: missing slice in first volume!\n"
00668 " detected at file: %s\n"
00669 " re-starting at file: %s\n"
00670 "*************************************************\n",
00671 p->fnames[p->flist[last+1].index],
00672 p->fnames[p->flist[testc].index] );
00673
00674
00675 *fl_start = p->flist[testc].index;
00676
00677 return -1;
00678 }
00679
00680
00681 return 0;
00682 }
00683
00684 return -1;
00685 }
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 static int volume_match( vol_t * vin, vol_t * vout, param_t * p, int start )
00700 {
00701 static int retry = 1;
00702 finfo_t * fp;
00703 finfo_t * fp_test;
00704 float z;
00705 int count, next_start = -1;
00706 int missing = 0;
00707
00708 if ( vin == NULL || vout == NULL ||
00709 p == NULL || p->flist == NULL || start < 0 )
00710 {
00711 fprintf( stderr, "failure: FMV: bad parameter data\n" );
00712 return -2;
00713 }
00714
00715 if ( (p->nused - start) < vin->nim )
00716 return 0;
00717
00718
00719
00720 fp = p->flist+start;
00721 for ( count = 0; count < vin->nim - 1; count++ )
00722 {
00723 z = vin->z_first + count * vin->z_delta;
00724
00725 if ( fabs( z - fp->geh.zoff ) > IFM_EPSILON )
00726 {
00727
00728
00729 fp_test = fp + 1;
00730 if ( fabs( z + vin->z_delta - fp_test->geh.zoff ) < IFM_EPSILON )
00731 {
00732
00733 if ( !check_error(&retry, vin->geh.tr, "slice out of order") )
00734 return 0;
00735
00736
00737
00738
00739 IFM_BIG_ERROR_MESG( "slice out of order!",
00740 p->fnames[fp->index], z, fp->geh.zoff,
00741 fp->geh.uv17, count + 1, vin->nim );
00742 }
00743 else if ( fabs(z + vin->z_delta - fp->geh.zoff) < IFM_EPSILON )
00744 {
00745
00746
00747
00748 if ( !check_error(&retry, vin->geh.tr, "slice missing") )
00749 return 0;
00750
00751
00752 missing++;
00753
00754 IFM_BIG_ERROR_MESG( "slice missing!",
00755 p->fnames[fp->index], z, fp->geh.zoff,
00756 fp->geh.uv17, count + 1, vin->nim );
00757
00758 count++;
00759 }
00760 else
00761 {
00762
00763 next_start = find_next_zoff( p, start+count, vin->z_first );
00764
00765 if ( next_start < 0 )
00766 return 0;
00767 else
00768 {
00769
00770 if ( !check_error(&retry, vin->geh.tr, "vol toasted") )
00771 return 0;
00772
00773 IFM_BIG_ERROR_MESG( "volume severely toasted!",
00774 p->fnames[fp->index], z, fp->geh.zoff,
00775 fp->geh.uv17, count + 1, vin->nim );
00776
00777 break;
00778 }
00779 }
00780 }
00781
00782 fp++;
00783 }
00784
00785 z = vin->z_first + count * vin->z_delta;
00786
00787 if ( count >= vin->nim )
00788 next_start = start + vin->nim - missing;
00789 else if ( (next_start < 0) && (fabs( z - fp->geh.zoff ) > IFM_EPSILON) )
00790 {
00791
00792 if ( (p->nused - start) <= vin->nim )
00793 return 0;
00794
00795 fp_test = fp + 1;
00796 if ( fabs( vin->z_first - fp_test->geh.zoff ) < IFM_EPSILON )
00797 {
00798
00799
00800
00801 if ( !check_error(&retry, vin->geh.tr, "last slice out of order") )
00802 return 0;
00803
00804 IFM_BIG_ERROR_MESG( "last slice out of order!",
00805 p->fnames[fp->index], z, fp->geh.zoff,
00806 fp->geh.uv17, count + 1, vin->nim );
00807 }
00808 else if ( fabs(vin->z_first - fp->geh.zoff) < IFM_EPSILON )
00809 {
00810
00811
00812
00813 if ( !check_error(&retry, vin->geh.tr, "last slice missing") )
00814 return 0;
00815
00816 missing++;
00817
00818 IFM_BIG_ERROR_MESG( "last slice missing!",
00819 p->fnames[fp->index], z, fp->geh.zoff,
00820 fp->geh.uv17, count + 1, vin->nim );
00821 }
00822 else
00823 {
00824
00825 next_start = find_next_zoff( p, start+count+1, vin->z_first );
00826
00827 if ( next_start < 0 )
00828 return 0;
00829 else
00830 {
00831
00832 if ( !check_error(&retry, vin->geh.tr, "Vol toasted") )
00833 return 0;
00834
00835 IFM_BIG_ERROR_MESG( "Volume severely toasted!",
00836 p->fnames[fp->index], z, fp->geh.zoff,
00837 fp->geh.uv17, count + 1, vin->nim );
00838 }
00839 }
00840 }
00841
00842 if ( next_start < 0)
00843 next_start = start + vin->nim - missing;
00844
00845 if ( retry == 0 && gD.level > 0 )
00846 fprintf(stderr," (retry OK - no errors)\n");
00847
00848 retry = 1;
00849
00850
00851
00852 vout->geh = p->flist[start].geh;
00853 vout->gex = p->flist[start].gex;
00854 vout->nim = next_start - start;
00855 vout->fl_1 = start;
00856 vout->fn_1 = p->flist[start].index;
00857 vout->fn_n = p->flist[start+vout->nim-1].index;
00858 strncpy( vout->first_file, p->fnames[vout->fn_1], IFM_MAX_FLEN );
00859 strncpy( vout->last_file, p->fnames[vout->fn_n], IFM_MAX_FLEN );
00860 vout->z_first = vin->z_first;
00861 vout->z_last = vin->z_last;
00862 vout->z_delta = vin->z_delta;
00863 vout->seq_num = -1;
00864 vout->run = vout->geh.uv17;
00865
00866 if ( vout->nim != vin->nim )
00867 return -1;
00868 else
00869 return 1;
00870 }
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880 static int check_error( int * retry, float tr, char * note )
00881 {
00882 if ( !retry )
00883 return -1;
00884
00885 if ( *retry == 1 )
00886 {
00887
00888 if ( gD.level > 0 )
00889 fprintf(stderr," (volume retry test for warning '%s'...)\n",
00890 CHECK_NULL_STR(note));
00891
00892 *retry = 0;
00893 sleep( nap_time_from_tr(tr) );
00894 return 0;
00895 }
00896
00897
00898
00899 *retry = 2;
00900
00901 return 1;
00902 }
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918 static int read_ge_files(
00919 param_t * p,
00920 int start,
00921 int max )
00922 {
00923 int n2scan;
00924 int next = start;
00925
00926 if ( p == NULL )
00927 {
00928 fputs( "failure: RAF: no param_t struct\n", stderr );
00929 return -1;
00930 }
00931
00932
00933 if ( p->fnames != NULL )
00934 {
00935 if ( p->nfiles <= 0 )
00936 {
00937 fputs( "failure: RAF: fnames does not match nfiles\n", stderr );
00938 return -1;
00939 }
00940
00941 MCW_free_expand( p->nfiles, p->fnames );
00942 p->fnames = NULL;
00943 }
00944
00945
00946 MCW_file_expand( 1, &p->glob_dir, &p->nfiles, &p->fnames );
00947
00948
00949 if ( (next == 0 ) && (p->opts.start_file != NULL) )
00950 {
00951 next = find_fl_file_index( p, p->opts.start_file );
00952
00953 if ( next < 0 )
00954 {
00955 if ( gD.level > 0 )
00956 {
00957 static int attempts = 0;
00958
00959 if ( attempts == 0 )
00960 fprintf(stderr, "-- still searching for start_file, '%s'\n",
00961 p->opts.start_file );
00962
00963 attempts++;
00964 }
00965 return 0;
00966 }
00967 }
00968
00969 if ( gD.level > 3 )
00970 {
00971 int fnum;
00972 for ( fnum = next; fnum < p->nfiles; fnum++ )
00973 printf( "file %4d: %s\n", fnum, p->fnames[fnum] );
00974 }
00975
00976 if ( p->nfiles <= 0 )
00977 return 0;
00978
00979
00980 if ( (max > 0) && (max <= (p->nfiles - next)) )
00981 n2scan = max;
00982 else
00983 n2scan = p->nfiles - next;
00984
00985
00986 if ( (n2scan > p->nalloc) || (max > p->nalloc) )
00987 {
00988 int nalloc;
00989
00990
00991 nalloc = (n2scan >= max) ? n2scan : max;
00992
00993 p->flist = (finfo_t *)realloc( p->flist, nalloc * sizeof(finfo_t) );
00994
00995 if ( p->flist == NULL )
00996 {
00997 fprintf(stderr, "failure to allocate %d finfo_t structs\n", nalloc);
00998 return -1;
00999 }
01000
01001 p->nalloc = nalloc;
01002
01003 if ( gD.level > 1 )
01004 {
01005 idisp_hf_param_t( "++ realloc of flist : ", p );
01006 fprintf( stderr, "-- n2scan = %d, max = %d\n", n2scan, max );
01007 }
01008 }
01009
01010 p->nused = scan_ge_files( p, next, n2scan );
01011
01012 if ( gD.level > 2 )
01013 idisp_hf_param_t( "end read_ge_files : ", p );
01014
01015
01016 return p->nused;
01017 }
01018
01019
01020
01021
01022
01023
01024
01025
01026 static int scan_ge_files (
01027 param_t * p,
01028 int next,
01029 int nfiles )
01030 {
01031 finfo_t * fp;
01032 int im_num, fnum;
01033 int files_read, rv;
01034 int need_M;
01035
01036 if ( nfiles <= 0 )
01037 return 0;
01038
01039 if ( check_im_store_space( &p->im_store, nfiles ) < 0 )
01040 return -1;
01041
01042 p->im_store.nused = 0;
01043
01044 for ( im_num = 0, fnum = next, fp = p->flist;
01045 im_num < nfiles;
01046 im_num++, fnum++, fp++ )
01047 {
01048 if ( im_num < p->im_store.nalloc )
01049 {
01050 fp->image = p->im_store.im_ary[im_num];
01051 need_M = 0;
01052 }
01053 else
01054 {
01055 fp->image = NULL;
01056 need_M = 1;
01057 }
01058
01059 rv = read_ge_image( p->fnames[fnum], fp, 1, need_M );
01060
01061
01062 if ( (need_M == 1) && (fp->image != NULL) )
01063 {
01064 p->im_store.im_ary[im_num] = fp->image;
01065 p->im_store.nalloc++;
01066
01067
01068 if ( p->im_store.im_size == 0 )
01069 {
01070 if ( alloc_x_im( &p->im_store, fp->bytes ) < 0 )
01071 return -1;
01072 }
01073
01074 if ( gD.level > 1 )
01075 fprintf( stderr, "++ allocated image %d at address %p\n",
01076 im_num, p->im_store.im_ary[im_num] );
01077 }
01078
01079 if ( (rv != 0) || (fp->geh.good != 1) )
01080 {
01081 static int read_failure = -1;
01082 static int fail_count = 0;
01083
01084
01085 if ( read_failure != fnum )
01086 {
01087 read_failure = fnum;
01088 fail_count = 1;
01089 }
01090 else
01091 fail_count++;
01092
01093
01094 if ( fail_count > IFM_MAX_GE_FAILURES )
01095 {
01096 fprintf( stderr, "\n** failure: cannot read GE header for "
01097 "file <%s>\n", p->fnames[fnum] );
01098 return -1;
01099 }
01100
01101
01102 if ( gD.level > 1 )
01103 fprintf( stderr, "\n-- (%d) failures to read GE header for "
01104 "file <%s>, trying again...\n",
01105 fail_count, p->fnames[fnum] );
01106
01107 break;
01108 }
01109 else
01110 {
01111 p->im_store.nused++;
01112 fp->index = fnum;
01113
01114 if ( gD.level > 2 )
01115 {
01116 idisp_ge_header_info( p->fnames[fp->index], &fp->geh );
01117 idisp_ge_extras( p->fnames[fp->index], &fp->gex );
01118 }
01119 }
01120 }
01121
01122
01123 files_read = fnum - next;
01124
01125 if ( gD.level > 1 )
01126 printf( "-- scanned %d GE files, from <%s> to <%s>\n",
01127 files_read, p->fnames[next], p->fnames[next+files_read-1] );
01128
01129 return files_read;
01130 }
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140 static int init_options( param_t * p, ART_comm * A, int argc, char * argv[] )
01141 {
01142 int ac, errors = 0;
01143
01144 if ( p == NULL )
01145 return 2;
01146
01147 if ( argc < 2 )
01148 {
01149 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01150 return 1;
01151 }
01152
01153
01154
01155 memset( p, 0, sizeof(*p) );
01156 memset( &gD, 0, sizeof(gD) );
01157 memset( &gS, 0, sizeof(gS) );
01158 memset( A, 0, sizeof(gAC) );
01159
01160 ART_init_AC_struct( A );
01161 A->param = p;
01162
01163 empty_string_list( &p->opts.drive_list, 0 );
01164 empty_string_list( &p->opts.rt_list, 0 );
01165
01166
01167 gD.level = 1;
01168
01169 for ( ac = 1; ac < argc; ac++ )
01170 {
01171 if ( ! strncmp( argv[ac], "-debug", 4 ) )
01172 {
01173 if ( ++ac >= argc )
01174 {
01175 fputs( "option usage: -debug LEVEL\n", stderr );
01176 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01177 return 1;
01178 }
01179
01180 p->opts.debug = atoi(argv[ac]);
01181 gD.level = p->opts.debug;
01182 if ( gD.level < 0 || gD.level > IFM_MAX_DEBUG )
01183 {
01184 fprintf( stderr, "error: debug level must be in [0,%d]\n",
01185 IFM_MAX_DEBUG );
01186 errors++;
01187 }
01188 }
01189 else if ( ! strncmp( argv[ac], "-GERT_Reco2", 7 ) )
01190 {
01191 p->opts.gert_reco = 1;
01192 }
01193 else if ( ! strncmp( argv[ac], "-help", 5 ) )
01194 {
01195 usage( IFM_PROG_NAME, IFM_USE_LONG );
01196 return 1;
01197 }
01198 else if ( ! strncmp( argv[ac], "-hist", 5 ) )
01199 {
01200 usage( IFM_PROG_NAME, IFM_USE_HIST );
01201 return 1;
01202 }
01203 else if ( ! strncmp( argv[ac], "-nice", 4 ) )
01204 {
01205 if ( ++ac >= argc )
01206 {
01207 fputs( "option usage: -nice INCREMENT\n", stderr );
01208 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01209 return 1;
01210 }
01211
01212 p->opts.nice = atoi(argv[ac]);
01213 if ( (p->opts.nice < IFM_MIN_NICE_INC) ||
01214 (p->opts.nice > IFM_MAX_NICE_INC) )
01215 {
01216 fprintf( stderr, "error: nice incrment must be in [%d,%d]\n",
01217 IFM_MIN_NICE_INC, IFM_MAX_NICE_INC );
01218 errors++;
01219 }
01220 }
01221 else if ( ! strncmp( argv[ac], "-nt", 3 ) )
01222 {
01223 if ( ++ac >= argc )
01224 {
01225 fputs( "option usage: -nt VOLUMES_PER_RUN\n", stderr );
01226 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01227 return 1;
01228 }
01229
01230 p->opts.nt = atoi(argv[ac]);
01231 if ( p->opts.nt < 0 || p->opts.nt > IFM_MAX_NT )
01232 {
01233 fprintf( stderr,
01234 "option usage: -nt VOLUMES_PER_RUN\n"
01235 " error: VOLUMES_PER_RUN must be in [%d,%d]\n",
01236 0, IFM_MAX_NT );
01237 errors++;
01238 }
01239 }
01240 else if ( ! strncmp( argv[ac], "-od", 3 ) ||
01241 ! strncmp( argv[ac], "-gert_outdir", 9 ) )
01242 {
01243 if ( ++ac >= argc )
01244 {
01245 fputs( "option usage: -gert_outdir OUTPUT_DIR\n", stderr );
01246 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01247 return 1;
01248 }
01249
01250 p->opts.gert_outdir = argv[ac];
01251 }
01252 else if ( ! strncmp( argv[ac], "-quiet", 6 ) )
01253 {
01254
01255 if ( gD.level == IFM_DEBUG_DEFAULT )
01256 gD.level = 0;
01257 }
01258 else if ( ! strncmp( argv[ac], "-quit", 5 ) )
01259 {
01260 p->opts.quit = 1;
01261 }
01262 else if ( ! strncmp( argv[ac], "-sp", 3 ) )
01263 {
01264 if ( ++ac >= argc )
01265 {
01266 fputs( "option usage: -sp PATTERN\n", stderr );
01267 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01268 return 1;
01269 }
01270
01271 p->opts.sp = argv[ac];
01272 }
01273 else if ( ! strncmp( argv[ac], "-start_dir", 8 ) )
01274 {
01275 if ( ++ac >= argc )
01276 {
01277 fputs( "option usage: -start_dir DIRECTORY\n", stderr );
01278 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01279 return 1;
01280 }
01281
01282 p->opts.start_dir = argv[ac];
01283 }
01284 else if ( ! strncmp( argv[ac], "-start_file", 8 ) )
01285 {
01286 if ( ++ac >= argc )
01287 {
01288 fputs( "option usage: -start_file DIR/FIRST_FILE\n", stderr );
01289 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01290 return 1;
01291 }
01292
01293 p->opts.start_file = argv[ac];
01294 }
01295 else if ( ! strncmp( argv[ac], "-version", 2 ) )
01296 {
01297 usage( IFM_PROG_NAME, IFM_USE_VERSION );
01298 return 1;
01299 }
01300
01301 else if ( ! strncmp( argv[ac], "-drive_afni", 6 ) )
01302 {
01303 if ( ++ac >= argc )
01304 {
01305 fputs( "option usage: -drive_afni COMMAND\n", stderr );
01306 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01307 return 1;
01308 }
01309
01310 if ( add_to_string_list( &p->opts.drive_list, argv[ac] ) != 0 )
01311 {
01312 fprintf(stderr,"** failed add '%s' to drive_list\n",argv[ac]);
01313 return 1;
01314 }
01315 }
01316 else if ( ! strncmp( argv[ac], "-host", 4 ) )
01317 {
01318 if ( ++ac >= argc )
01319 {
01320 fputs( "option usage: -host HOSTNAME\n", stderr );
01321 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01322 return 1;
01323 }
01324
01325 p->opts.host = argv[ac];
01326 strncpy( A->host, argv[ac], ART_NAME_LEN-1 );
01327 A->host[ART_NAME_LEN-1] = '\0';
01328 }
01329 else if ( ! strncmp( argv[ac], "-rev_byte_order", 4 ) )
01330 {
01331 p->opts.rev_bo = 1;
01332 }
01333 else if ( ! strncmp( argv[ac], "-rt_cmd", 6 ) )
01334 {
01335 if ( ++ac >= argc )
01336 {
01337 fputs( "option usage: -rt_cmd COMMAND\n", stderr );
01338 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01339 return 1;
01340 }
01341
01342 if ( add_to_string_list( &p->opts.rt_list, argv[ac] ) != 0 )
01343 {
01344 fprintf(stderr,"** failed add '%s' to rt_list\n",argv[ac]);
01345 return 1;
01346 }
01347 }
01348 else if ( ! strncmp( argv[ac], "-rt", 3 ) )
01349 {
01350 A->state = ART_STATE_TO_OPEN;
01351 p->opts.rt = 1;
01352 }
01353 else if ( ! strncmp( argv[ac], "-swap", 5 ) )
01354 {
01355 A->swap = 1;
01356 p->opts.swap = 1;
01357 }
01358 else if ( ! strncmp( argv[ac], "-zorder", 6 ) )
01359 {
01360 if ( ++ac >= argc )
01361 {
01362 fputs( "option usage: -zorder ORDER\n", stderr );
01363 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01364 return 1;
01365 }
01366
01367 A->zorder = argv[ac];
01368 }
01369 else
01370 {
01371 fprintf( stderr, "error: invalid option <%s>\n\n", argv[ac] );
01372 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01373 return 1;
01374 }
01375 }
01376
01377 if ( errors > 0 )
01378 {
01379 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01380 return 1;
01381 }
01382
01383 if ( p->opts.start_dir == NULL )
01384 {
01385 fputs( "error: missing '-start_dir DIR' option\n", stderr );
01386 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01387 return 1;
01388 }
01389
01390 if ( p->opts.rev_bo && p->opts.swap )
01391 {
01392 fprintf( stderr, "error: options '-rev_byte_order' and '-swap' "
01393 "cannot both be used\n");
01394 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01395 return 1;
01396 }
01397
01398 if ( A->zorder )
01399 {
01400 if ( strcmp(A->zorder, "alt") && strcmp(A->zorder, "seq") )
01401 {
01402 fprintf(stderr,"** order '%s' is invalid for '-zorder' option,\n"
01403 " must be either 'alt' or 'seq'\n", A->zorder);
01404 return -1;
01405 }
01406 }
01407
01408
01409
01410 if ( dir_expansion_form( p->opts.start_dir, &p->glob_dir ) != 0 )
01411 return 2;
01412
01413
01414 p->opts.argv = argv;
01415 p->opts.argc = argc;
01416
01417 p->ftype = IFM_IM_FTYPE_GEMS5;
01418
01419 if ( gD.level > 1 )
01420 {
01421 idisp_hf_opts_t ( "end init_options : ", &p->opts );
01422 idisp_hf_param_t( "end init_options : ", p );
01423 }
01424
01425 if ( gD.level > 0 )
01426 fprintf( stderr, "\n%s running, use <ctrl-c> to quit...\n\n",
01427 IFM_PROG_NAME );
01428
01429 return 0;
01430 }
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441 static int init_extras( param_t * p, ART_comm * ac )
01442 {
01443 if ( p->opts.nice && set_nice_level(p->opts.nice) )
01444 return 1;
01445
01446 if ( ac->state == ART_STATE_TO_OPEN )
01447 {
01448 atexit( ART_exit );
01449 ac->mode = AFNI_OPEN_CONTROL_MODE;
01450 ART_open_afni_link( ac, 2, 1, gD.level );
01451 }
01452
01453
01454 if ( p->opts.start_file != NULL )
01455 {
01456 char * sf = p->opts.start_file;
01457 char * gd = p->glob_dir;
01458 int flevel = str_char_count( sf, strlen(sf), (char)'/' );
01459
01460
01461 if ( flevel != str_char_count( gd, strlen(gd), (char)'/' ) )
01462 {
01463 fprintf( stderr,
01464 "** warning : relative path to : '-start_dir %s'\n"
01465 " does not seem to match : '-start_file %s'\n"
01466 " (so 'start_file' may never be found)\n\n",
01467 p->opts.start_file, p->opts.start_dir );
01468 }
01469 else if ( gD.level > 1 )
01470 fprintf( stderr, "-- '-start_file %s' and\n"
01471 " '-start_dir %s' match at dir level %d\n",
01472 p->opts.start_file, p->opts.start_dir, flevel );
01473 }
01474
01475 return 0;
01476 }
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486 static int set_nice_level( int level )
01487 {
01488 int rv;
01489
01490 rv = nice( level );
01491 if ( rv != 0 )
01492 {
01493 if ( level < 0 )
01494 fprintf( stderr, "error: only root may decrement nice value\n"
01495 " (errno = %d, rv = %d)\n", errno, rv );
01496 else
01497 fprintf( stderr,
01498 "error: failure to adjust nice by %d\n"
01499 " (errno = %d, rv = %d)\n", level, errno, rv );
01500 }
01501 else if ( gD.level > 1 )
01502 fprintf( stderr, "-- nice value incremented by %d\n", level );
01503
01504 return rv;
01505 }
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520 int dir_expansion_form( char * sin, char ** sexp )
01521 {
01522 char * out;
01523 char * cp;
01524 char d0, d1, d2;
01525 int len;
01526
01527 if ( (sin == NULL) || (sexp == NULL) )
01528 return -1;
01529
01530 *sexp = NULL;
01531 len = strlen(sin);
01532
01533 out = (char *)malloc((len + IFM_PAD_LEN) * sizeof(char));
01534 if ( out == NULL )
01535 {
01536 fprintf( stderr, "failure: dir_expansion_form malloc\n" );
01537 return -1;
01538 }
01539
01540 *sexp = out;
01541
01542 strcpy( out,sin );
01543
01544 cp = out + len - 1;
01545
01546
01547 while ( (cp > (out+2)) && !isdigit( *cp ) )
01548 cp--;
01549
01550 if ( !isdigit(*cp) )
01551 {
01552 fprintf( stderr, "error: dir <%s> is not of the form 00n (e.g. 003)\n",
01553 sin );
01554 free(out);
01555 return -1;
01556 }
01557
01558 cp -= 2;
01559
01560 d0 = cp[0];
01561 d1 = cp[1];
01562 d2 = cp[2];
01563
01564 if ( (d0 != '0') ||
01565 ( (d1 != '0') && (d1 != '1')) )
01566 {
01567 fprintf( stderr, "error: dir <%s> is not of the form 0[01]n"
01568 " (e.g. 003)\n", sin );
01569 free(out);
01570 return -1;
01571 }
01572
01573
01574
01575
01576 strcpy( cp, "[0-9]" );
01577 cp += strlen( "[0-9]" );
01578
01579 if ( d1 == '0' )
01580 strcpy( cp, "[02468]" );
01581 else
01582 strcpy( cp, "[13579]" );
01583 cp += strlen( "[02468]" );
01584
01585 *cp++ = d2;
01586
01587
01588 strcpy( cp, "/[Ii].*" );
01589
01590 return 0;
01591 }
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601 static int read_ge_image( char * pathname, finfo_t * fp,
01602 int get_image, int need_memory )
01603 {
01604 ge_header_info * hi = &fp->geh;
01605
01606 FILE *imfile ;
01607 int length , skip , swap=0 ;
01608 char orients[8] , str[8] ;
01609 int nx , ny , bpp , cflag , hdroff ;
01610 float uv17 = -1.0;
01611
01612 if( hi == NULL ) return -1;
01613 hi->good = 0 ;
01614 if( pathname == NULL ||
01615 pathname[0] == '\0' ) return -1;
01616
01617 length = l_THD_filesize( pathname ) ;
01618 if( length < 1024 ) return -1;
01619
01620 imfile = fopen( pathname , "r" ) ;
01621 if( imfile == NULL ) return -1;
01622
01623 strcpy(str,"JUNK") ;
01624 fread(str,1,4,imfile) ;
01625
01626 if( str[0]!='I' || str[1]!='M' || str[2]!='G' || str[3]!='F' ){
01627 fclose(imfile) ; return -2;
01628 }
01629
01630
01631
01632 fread( &skip , 4,1, imfile ) ;
01633 fread( &nx , 4,1, imfile ) ;
01634 fread( &ny , 4,1, imfile ) ;
01635 fread( &bpp , 4,1, imfile ) ;
01636 fread( &cflag, 4,1, imfile ) ;
01637
01638
01639
01640 if( nx < 0 || nx > 8192 ){
01641 swap = 1 ;
01642 swap_4(&skip); swap_4(&nx); swap_4(&ny); swap_4(&bpp); swap_4(&cflag);
01643 } else {
01644 swap = 0 ;
01645 }
01646 if( nx < 0 || nx > 8192 || ny < 0 || ny > 8192 ){
01647 fclose(imfile) ; return -1;
01648 }
01649
01650 hi->nx = nx ;
01651 hi->ny = ny ;
01652
01653 if( skip+2*nx*ny > length ||
01654 skip <= 0 ||
01655 cflag != 1 ||
01656 bpp != 16 ){
01657 fclose(imfile); return -1;
01658 }
01659
01660
01661
01662 fseek( imfile , 148L , SEEK_SET ) ;
01663 fread( &hdroff , 4,1 , imfile ) ;
01664 if( swap ) swap_4(&hdroff) ;
01665
01666 if( hdroff > 0 && hdroff+256 < length ){
01667 float dx,dy,dz, xyz[9], zz ; int itr, ii,jj,kk ;
01668
01669
01670
01671 fseek( imfile , hdroff+26 , SEEK_SET ) ;
01672 fread( &dz , 4,1 , imfile ) ;
01673
01674 fseek( imfile , hdroff+50 , SEEK_SET ) ;
01675 fread( &dx , 4,1 , imfile ) ;
01676 fread( &dy , 4,1 , imfile ) ;
01677
01678 if( swap ){ swap_4(&dx); swap_4(&dy); swap_4(&dz); }
01679
01680 hi->dx = dx ; hi->dy = dy ; hi->dz = dz ;
01681
01682
01683
01684
01685
01686
01687
01688 fseek( imfile , hdroff+154 , SEEK_SET ) ;
01689 fread( xyz , 4,9 , imfile ) ;
01690 if( swap ){
01691 swap_4(xyz+0); swap_4(xyz+1); swap_4(xyz+2);
01692 swap_4(xyz+3); swap_4(xyz+4); swap_4(xyz+5);
01693 swap_4(xyz+6); swap_4(xyz+7); swap_4(xyz+8);
01694 }
01695
01696
01697
01698
01699
01700
01701 dx = fabs(xyz[3]-xyz[0]) ; ii = 1 ;
01702 dy = fabs(xyz[4]-xyz[1]) ; if( dy > dx ){ ii=2; dx=dy; }
01703 dz = fabs(xyz[5]-xyz[2]) ; if( dz > dx ){ ii=3; }
01704 dx = xyz[ii+2]-xyz[ii-1] ; if( dx < 0. ){ ii = -ii; }
01705 switch( ii ){
01706 case 1: orients[0]= 'L'; orients[1]= 'R'; break;
01707 case -1: orients[0]= 'R'; orients[1]= 'L'; break;
01708 case 2: orients[0]= 'P'; orients[1]= 'A'; break;
01709 case -2: orients[0]= 'A'; orients[1]= 'P'; break;
01710 case 3: orients[0]= 'I'; orients[1]= 'S'; break;
01711 case -3: orients[0]= 'S'; orients[1]= 'I'; break;
01712 default: orients[0]='\0'; orients[1]='\0'; break;
01713 }
01714
01715
01716
01717
01718
01719
01720 dx = fabs(xyz[6]-xyz[3]) ; jj = 1 ;
01721 dy = fabs(xyz[7]-xyz[4]) ; if( dy > dx ){ jj=2; dx=dy; }
01722 dz = fabs(xyz[8]-xyz[5]) ; if( dz > dx ){ jj=3; }
01723 dx = xyz[jj+5]-xyz[jj+2] ; if( dx < 0. ){ jj = -jj; }
01724 switch( jj ){
01725 case 1: orients[2] = 'L'; orients[3] = 'R'; break;
01726 case -1: orients[2] = 'R'; orients[3] = 'L'; break;
01727 case 2: orients[2] = 'P'; orients[3] = 'A'; break;
01728 case -2: orients[2] = 'A'; orients[3] = 'P'; break;
01729 case 3: orients[2] = 'I'; orients[3] = 'S'; break;
01730 case -3: orients[2] = 'S'; orients[3] = 'I'; break;
01731 default: orients[2] ='\0'; orients[3] ='\0'; break;
01732 }
01733
01734 orients[4] = '\0' ;
01735
01736 kk = 6 - abs(ii)-abs(jj) ;
01737
01738
01739
01740 zz = xyz[kk-1] ;
01741
01742 hi->zoff = zz ;
01743 strcpy(hi->orients,orients) ;
01744
01745
01746
01747 fp->gex.xorg = xyz[abs(ii)-1];
01748 fp->gex.yorg = xyz[abs(jj)-1];
01749
01750
01751
01752 fseek( imfile , hdroff+194 , SEEK_SET ) ;
01753 fread( &itr , 4,1 , imfile ) ;
01754 if( swap ) swap_4(&itr) ;
01755 hi->tr = 1.0e-6 * itr ;
01756
01757
01758
01759 fseek( imfile , hdroff+202 , SEEK_SET ) ;
01760 fread( &itr , 4,1 , imfile ) ;
01761 if( swap ) swap_4(&itr) ;
01762 hi->te = 1.0e-6 * itr ;
01763
01764
01765
01766
01767
01768
01769
01770 fseek ( imfile , hdroff+272+202, SEEK_SET ) ;
01771 fread( &uv17 , 4, 1 , imfile ) ;
01772 if( swap ) swap_4(&uv17) ;
01773
01774 hi->uv17 = (int)uv17;
01775
01776
01777
01778 fp->gex.bpp = bpp;
01779 fp->gex.cflag = cflag;
01780 fp->gex.hdroff = hdroff;
01781 fp->gex.skip = skip;
01782 fp->gex.swap = swap;
01783 fp->gex.kk = kk;
01784
01785 memcpy( fp->gex.xyz, xyz, sizeof(xyz) );
01786
01787 hi->good = 1 ;
01788
01789 }
01790
01791
01792 if ( get_image )
01793 {
01794 int elements = hi->nx * hi->ny;
01795
01796 fp->bytes = elements * 2;
01797
01798 if ( need_memory )
01799 fp->image = malloc( fp->bytes );
01800
01801 if ( fp->image == NULL )
01802 {
01803 fprintf(stderr, "** RGI: no memory for %d byte image\n", fp->bytes);
01804 hi->good = 0;
01805 return -1;
01806 }
01807
01808 fseek ( imfile, skip, SEEK_SET );
01809 if ( fread( fp->image , 2, elements, imfile ) != elements )
01810 {
01811 fprintf( stderr, "** RGI: failed to read %d shorts from %s\n",
01812 elements, pathname );
01813 hi->good = 0;
01814 return -1;
01815 }
01816 }
01817
01818 fclose(imfile);
01819 return 0;
01820 }
01821
01822
01823
01824
01825
01826
01827 static int swap_4( void * ptr )
01828 {
01829 unsigned char * addr = ptr;
01830
01831 addr[0] ^= addr[3]; addr[3] ^= addr[0]; addr[0] ^= addr[3];
01832 addr[1] ^= addr[2]; addr[2] ^= addr[1]; addr[1] ^= addr[2];
01833
01834 return 0;
01835 }
01836
01837
01838
01839
01840
01841
01842 static int idisp_im_store_t( char * info, im_store_t * is )
01843 {
01844 if ( info )
01845 fputs( info, stdout );
01846
01847 if ( is == NULL )
01848 {
01849 printf( "idisp_im_store_t: is == NULL\n" );
01850 return -1;
01851 }
01852
01853 printf( "im_store_t struct at %p :\n"
01854 " (nalloc, nused) = (%d, %d)\n"
01855 " (ary_len, im_size) = (%d, %d)\n"
01856 " (im_ary, x_im) = (%p, %p)\n",
01857 is, is->nalloc, is->nused,
01858 is->ary_len, is->im_size, is->im_ary, is->x_im );
01859
01860 return 0;
01861 }
01862
01863
01864
01865
01866
01867
01868 static int idisp_hf_param_t( char * info, param_t * p )
01869 {
01870 if ( info )
01871 fputs( info, stdout );
01872
01873 if ( p == NULL )
01874 {
01875 printf( "idisp_hf_param_t: p == NULL\n" );
01876 return -1;
01877 }
01878
01879 printf( "param_t struct at %p :\n"
01880 " ftype =%d\n"
01881 " (nused, nalloc) = (%d, %d)\n"
01882 " flist = %p\n"
01883 " glob_dir = %s\n"
01884 " nfiles = %d\n"
01885 " fnames = %p\n",
01886 p, p->ftype, p->nused, p->nalloc, p->flist,
01887 CHECK_NULL_STR(p->glob_dir),
01888 p->nfiles, p->fnames );
01889
01890 return 0;
01891 }
01892
01893
01894
01895
01896
01897
01898 static int idisp_hf_opts_t( char * info, opts_t * opt )
01899 {
01900 if ( info )
01901 fputs( info, stdout );
01902
01903 if ( opt == NULL )
01904 {
01905 printf( "idisp_hf_opts_t: opt == NULL\n" );
01906 return -1;
01907 }
01908
01909 printf( "opts_t struct at %p :\n"
01910 " start_file = %s\n"
01911 " start_dir = %s\n"
01912 " sp = %s\n"
01913 " gert_outdir = %s\n"
01914 " (argv, argc) = (%p, %d)\n"
01915 " (nt, nice) = (%d, %d)\n"
01916 " (debug, gert_reco) = (%d, %d)\n"
01917 " quit = %d\n"
01918 " (rt, swap, rev_bo) = (%d, %d, %d)\n"
01919 " host = %s\n"
01920 " drive_list(u,a,p) = %d, %d, %p\n"
01921 " rt_list (u,a,p) = %d, %d, %p\n",
01922 opt,
01923 CHECK_NULL_STR(opt->start_file),
01924 CHECK_NULL_STR(opt->start_dir),
01925 CHECK_NULL_STR(opt->sp),
01926 CHECK_NULL_STR(opt->gert_outdir),
01927 opt->argv, opt->argc,
01928 opt->nt, opt->nice,
01929 opt->debug, opt->gert_reco, opt->quit,
01930 opt->rt, opt->swap, opt->rev_bo,
01931 CHECK_NULL_STR(opt->host),
01932 opt->drive_list.nused, opt->drive_list.nalloc, opt->drive_list.str,
01933 opt->rt_list.nused, opt->rt_list.nalloc, opt->rt_list.str
01934 );
01935
01936 return 0;
01937 }
01938
01939
01940
01941
01942
01943
01944 static int idisp_hf_vol_t( char * info, vol_t * v )
01945 {
01946 if ( info )
01947 fputs( info, stdout );
01948
01949 if ( v == NULL )
01950 {
01951 printf( "idisp_hf_vol_t: v == NULL\n" );
01952 return -1;
01953 }
01954
01955 printf( "vol_t struct at %p :\n"
01956 " nim = %d\n"
01957 " (fl_1, fn_1, fn_n) = (%d, %d, %d)\n"
01958 " first_file = %s\n"
01959 " last_file = %s\n"
01960 " (z_first, z_last) = (%f, %f)\n"
01961 " z_delta = %f\n"
01962 " (seq_num, run) = (%d, %d)\n",
01963 v, v->nim, v->fl_1, v->fn_1, v->fn_n,
01964 v->first_file, v->last_file,
01965 v->z_first, v->z_last, v->z_delta,
01966 v->seq_num, v->run );
01967
01968 idisp_ge_header_info( info, &v->geh );
01969 idisp_ge_extras( info, &v->gex );
01970
01971 return 0;
01972 }
01973
01974
01975
01976
01977
01978
01979
01980 static int idisp_ge_extras( char * info, ge_extras * E )
01981 {
01982 if ( info )
01983 fputs( info, stdout );
01984
01985 if ( E == NULL )
01986 {
01987 printf( "idisp_ge_extras: E == NULL\n" );
01988 return -1;
01989 }
01990
01991 printf( "ge_extras at %p :\n"
01992 " bpp = %d\n"
01993 " cflag = %d\n"
01994 " hdroff = %d\n"
01995 " skip = %d\n"
01996 " swap = %d\n"
01997 " kk = %d\n"
01998 " xorg = %f\n"
01999 " yorg = %f\n"
02000 " (xyz0,xyz1,xyz2) = (%f,%f,%f)\n"
02001 " (xyz3,xyz4,xyz5) = (%f,%f,%f)\n"
02002 " (xyz6,xyz7,xyz8) = (%f,%f,%f)\n",
02003 E, E->bpp, E->cflag, E->hdroff, E->skip, E->swap, E->kk,
02004 E->xorg, E->yorg,
02005 E->xyz[0], E->xyz[1], E->xyz[2],
02006 E->xyz[3], E->xyz[4], E->xyz[5],
02007 E->xyz[6], E->xyz[7], E->xyz[8]
02008 );
02009 return 0;
02010 }
02011
02012
02013
02014
02015
02016
02017 static int idisp_ge_header_info( char * info, ge_header_info * I )
02018 {
02019 if ( info )
02020 fputs( info, stdout );
02021
02022 if ( I == NULL )
02023 {
02024 printf( "idisp_ge_header_info: I == NULL\n" );
02025 return -1;
02026 }
02027
02028 printf( "ge_header_info at %p :\n"
02029 " good = %d\n"
02030 " (nx,ny) = (%d,%d)\n"
02031 " uv17 = %d\n"
02032 " (dx,dy,dz) = (%f,%f,%f)\n"
02033 " zoff = %f\n"
02034 " (tr,te) = (%f,%f)\n"
02035 " orients = %-8s\n",
02036 I, I->good, I->nx, I->ny, I->uv17,
02037 I->dx, I->dy, I->dz, I->zoff, I->tr, I->te,
02038 CHECK_NULL_STR(I->orients)
02039 );
02040
02041 return 0;
02042 }
02043
02044
02045
02046
02047
02048 static int usage ( char * prog, int level )
02049 {
02050 if ( level == IFM_USE_SHORT )
02051 {
02052 fprintf( stderr,
02053 "usage: %s [options] -start_dir DIR\n"
02054 "usage: %s -help\n",
02055 prog, prog );
02056 return 0;
02057 }
02058 else if ( level == IFM_USE_LONG )
02059 {
02060 printf(
02061 "\n"
02062 "%s - monitor real-time acquisition of I-files\n"
02063 "\n"
02064 " This program is intended to be run during a scanning session\n"
02065 " on a GE scanner, to monitor the collection of I-files. The\n"
02066 " user will be notified of any missing slice or any slice that\n"
02067 " is aquired out of order.\n"
02068 "\n"
02069 " It is recommended that the user runs '%s' just after the\n"
02070 " scanner is first prepped, and then watches for error messages\n"
02071 " during the scanning session. The user should terminate the\n"
02072 " program whey they are done with all runs.\n"
02073 "\n"
02074 " Note that '%s' can also be run separate from scanning, either\n"
02075 " to verify the integrity of I-files, or to create a GERT_Reco2\n"
02076 " script, which is used to create AFNI datasets.\n"
02077 "\n"
02078 " At the present time, the user must use <ctrl-c> to terminate\n"
02079 " the program.\n"
02080 "\n"
02081 " ---------------------------------------------------------------\n"
02082 " usage: %s [options] -start_dir DIR\n"
02083 "\n"
02084 " ---------------------------------------------------------------\n"
02085 " examples (no real-time options):\n"
02086 "\n"
02087 " %s -start_dir 003\n"
02088 " %s -help\n"
02089 " %s -start_dir 003 -GERT_reco2 -quit\n"
02090 " %s -start_dir 003 -nt 120 -start_file 043/I.901\n"
02091 " %s -debug 2 -nice 10 -start_dir 003\n"
02092 "\n"
02093 " examples (with real-time options):\n"
02094 "\n"
02095 " %s -start_dir 003 -rt\n"
02096 " %s -start_dir 003 -rt -host pickle\n"
02097 " %s -start_dir 003 -nt 120 -rt -host pickle\n"
02098 "\n"
02099 " ** detailed real-time example:\n"
02100 "\n"
02101 " This example scans data starting from directory 003, expects\n"
02102 " 160 repetitions (TRs), and invokes the real-time processing,\n"
02103 " sending data to a computer called some.remote.computer.name\n"
02104 " (where afni is running, and which considers THIS computer to\n"
02105 " be trusted - see the AFNI_TRUSTHOST environment variable).\n"
02106 "\n"
02107 " Multiple DRIVE_AFNI commands are passed through '-drive_afni'\n"
02108 " options, one requesting to open an axial image window, and\n"
02109 " another requesting an axial graph, with 160 data points.\n"
02110 "\n"
02111 " See README.driver for acceptable DRIVE_AFNI commands.\n"
02112 "\n"
02113 " Also, multiple commands specific to the real-time plugin are\n"
02114 " passed via the '-rt_cmd' options. The 'REFIX command sets the\n"
02115 " prefix for the datasets output by afni. The GRAPH_XRANGE and\n"
02116 " GRAPH_YRANGE commands set the graph dimensions for the 3D\n"
02117 " motion correction graph (only). And the GRAPH_EXPR command\n"
02118 " is used to replace the 6 default motion correction graphs with\n"
02119 " a single graph, according to the given expression, the square\n"
02120 " root of the average squared entry of the 3 rotaion parameters,\n"
02121 " roll, pitch and yaw, ignoring the 3 shift parameters, dx, dy\n"
02122 " and dz.\n"
02123 "\n"
02124 " See README.realtime for acceptable DRIVE_AFNI commands.\n"
02125 "\n"
02126 " %s \\\n"
02127 " -start_dir 003 \\\n"
02128 " -nt 160 \\\n"
02129 " -rt \\\n"
02130 " -host some.remote.computer.name \\\n"
02131 " -drive_afni 'OPEN_WINDOW axialimage' \\\n"
02132 " -drive_afni 'OPEN_WINDOW axialgraph pinnum=160' \\\n"
02133 " -rt_cmd 'PREFIX eat.more.cheese' \\\n"
02134 " -rt_cmd 'GRAPH_XRANGE 160' \\\n"
02135 " -rt_cmd 'GRAPH_YRANGE 1.02' \\\n"
02136 " -rt_cmd 'GRAPH_EXPR sqrt((d*d+e*e+f*f)/3)' \n"
02137 "\n"
02138 " ---------------------------------------------------------------\n"
02139 " notes:\n"
02140 "\n"
02141 " - Once started, this program exits only when a fatal error\n"
02142 " occurs (single missing or out of order slices are not\n"
02143 " considered fatal).\n"
02144 "\n"
02145 " ** This has been modified. The '-quit' option tells Imon\n"
02146 " to terminate once it runs out of new data to use.\n"
02147 "\n"
02148 " - To terminate this program, use <ctrl-c>.\n"
02149 "\n"
02150 " ---------------------------------------------------------------\n"
02151 " main option:\n"
02152 "\n"
02153 " -start_dir DIR : (REQUIRED) specify starting directory\n"
02154 "\n"
02155 " e.g. -start_dir 003\n"
02156 "\n"
02157 " The starting directory, DIR, must be of the form 00n,\n"
02158 " where n is a digit. The program then monitors all\n"
02159 " directories of the form ??n, created by the GE scanner.\n"
02160 "\n"
02161 " For instance, with the option '-start_dir 003', this\n"
02162 " program watches for new directories 003, 023, 043, etc.\n"
02163 "\n"
02164 " ---------------------------------------------------------------\n"
02165 " real-time options:\n"
02166 "\n"
02167 " -rt : specify to use the real-time facility\n"
02168 "\n"
02169 " With this option, the user tells '%s' to use the real-time\n"
02170 " facility, passing each volume of images to an existing\n"
02171 " afni process on some machine (as specified by the '-host'\n"
02172 " option). Whenever a new volume is aquired, it will be\n"
02173 " sent to the afni program for immediate update.\n"
02174 "\n"
02175 " Note that afni must also be started with the '-rt' option\n"
02176 " to make use of this.\n"
02177 "\n"
02178 " Note also that the '-host HOSTNAME' option is not required\n"
02179 " if afni is running on the same machine.\n"
02180 "\n"
02181 " -drive_afni CMND : send 'drive afni' command, CMND\n"
02182 "\n"
02183 " e.g. -drive_afni 'OPEN_WINDOW axialimage'\n"
02184 "\n"
02185 " This option is used to pass a single DRIVE_AFNI command\n"
02186 " to afni. For example, 'OPEN_WINDOW axialimage' will open\n"
02187 " such an axial view window on the afni controller.\n"
02188 "\n"
02189 " Note: the command 'CMND' must be given in quotes, so that\n"
02190 " the shell will send it as a single parameter.\n"
02191 "\n"
02192 " Note: this option may be used multiple times.\n"
02193 "\n"
02194 " See README.driver for more details.\n"
02195 "\n"
02196 " -host HOSTNAME : specify the host for afni communication\n"
02197 "\n"
02198 " e.g. -host mycomputer.dot.my.network\n"
02199 " e.g. -host 127.0.0.127\n"
02200 " e.g. -host mycomputer\n"
02201 " the default host is 'localhost'\n"
02202 "\n"
02203 " The specified HOSTNAME represents the machine that is\n"
02204 " running afni. Images will be sent to afni on this machine\n"
02205 " during the execution of '%s'.\n"
02206 "\n"
02207 " Note that the enviroment variable AFNI_TRUSTHOST must be\n"
02208 " set on the machine running afni. Set this equal to the\n"
02209 " name of the machine running Imon (so that afni knows to\n"
02210 " accept the data from the sending machine).\n"
02211 "\n"
02212 " -rev_byte_order : pass the reverse of the BYTEORDER to afni\n"
02213 "\n"
02214 " Reverse the byte order that is given to afni. In case the\n"
02215 " detected byte order is not what is desired, this option\n"
02216 " can be used to reverse it.\n"
02217 "\n"
02218 " See the (obsolete) '-swap' option for more details.\n"
02219 "\n"
02220 " -rt_cmd COMMAND : send COMMAND(s) to realtime plugin\n"
02221 "\n"
02222 " e.g. -rt_cmd 'GRAPH_XRANGE 120'\n"
02223 " e.g. -rt_cmd 'GRAPH_XRANGE 120 \\n GRAPH_YRANGE 2.5'\n"
02224 "\n"
02225 " This option is used to pass commands to the realtime\n"
02226 " plugin. For example, 'GRAPH_XRANGE 120' will set the\n"
02227 " x-scale of the motion graph window to 120 (repetitions).\n"
02228 "\n"
02229 " Note: the command 'COMMAND' must be given in quotes, so\n"
02230 " that the shell will send it as a single parameter.\n"
02231 "\n"
02232 " Note: this option may be used multiple times.\n"
02233 "\n"
02234 " See README.realtime for more details.\n"
02235 "\n"
02236 " -swap (obsolete) : swap data bytes before sending to afni\n"
02237 "\n"
02238 " Since afni may be running on a different machine, the byte\n"
02239 " order may differ there. This option will force the bytes\n"
02240 " to be reversed, before sending the data to afni.\n"
02241 "\n"
02242 " ** As of version 3.0, this option should not be necessary.\n"
02243 " '%s' detects the byte order of the image data, and then\n"
02244 " passes that information to afni. The realtime plugin\n"
02245 " will (now) decide whether to swap bytes in the viewer.\n"
02246 "\n"
02247 " If for some reason the user wishes to reverse the order\n"
02248 " from what is detected, '-rev_byte_order' can be used.\n"
02249 "\n"
02250 " -zorder ORDER : slice order over time\n"
02251 "\n"
02252 " e.g. -zorder alt\n"
02253 " e.g. -zorder seq\n"
02254 " the default is 'alt'\n"
02255 "\n"
02256 " This options allows the user to alter the slice\n"
02257 " acquisition order in real-time mode, simliar to the slice\n"
02258 " pattern of the '-sp' option. The main differences are:\n"
02259 " o only two choices are presently available\n"
02260 " o the syntax is intentionally different (from that\n"
02261 " of 'to3d' or the '-sp' option)\n"
02262 "\n"
02263 " ORDER values:\n"
02264 " alt : alternating in the Z direction (over time)\n"
02265 " seq : sequential in the Z direction (over time)\n"
02266 "\n"
02267 " ---------------------------------------------------------------\n"
02268 " other options:\n"
02269 "\n"
02270 " -debug LEVEL : show debug information during execution\n"
02271 "\n"
02272 " e.g. -debug 2\n"
02273 " the default level is 1, the domain is [0,3]\n"
02274 " the '-quiet' option is equivalent to '-debug 0'\n"
02275 "\n"
02276 " -help : show this help information\n"
02277 "\n"
02278 " -hist : display a history of program changes\n"
02279 "\n"
02280 " -nice INCREMENT : adjust the nice value for the process\n"
02281 "\n"
02282 " e.g. -nice 10\n"
02283 " the default is 0, and the maximum is 20\n"
02284 " a superuser may use down to the minimum of -19\n"
02285 "\n"
02286 " A positive INCREMENT to the nice value of a process will\n"
02287 " lower its priority, allowing other processes more CPU\n"
02288 " time.\n"
02289 "\n"
02290 " -nt VOLUMES_PER_RUN : set the number of time points per run\n"
02291 "\n"
02292 " e.g. -nt 120\n"
02293 "\n"
02294 " With this option, if a run stalls before the specified\n"
02295 " VOLUMES_PER_RUN is reached (notably including the first\n"
02296 " run), the user will be notified.\n"
02297 "\n"
02298 " Without this option, %s will compute the expected number\n"
02299 " of time points per run based on the first run (and will\n"
02300 " allow the value to increase based on subsequent runs).\n"
02301 " Therefore %s would not detect a stalled first run.\n"
02302 "\n"
02303 " -quiet : show only errors and final information\n"
02304 "\n"
02305 " -quit : quit when there is no new data\n"
02306 "\n"
02307 " With this option, the program will terminate once a delay\n"
02308 " in new data occurs. This is most appropriate to use when\n"
02309 " the image files have already been collected.\n"
02310 "\n"
02311 " -start_file S_FILE : have %s process starting at S_FILE\n"
02312 "\n"
02313 " e.g. -start_file 043/I.901\n"
02314 "\n"
02315 " With this option, any earlier I-files will be ignored\n"
02316 " by %s. This is a good way to start processing a later\n"
02317 " run, if it desired not to look at the earlier data.\n"
02318 "\n"
02319 " In this example, all files in directories 003 and 023\n"
02320 " would be ignored, along with everything in 043 up through\n"
02321 " I.900. So 043/I.901 might be the first file in run 2.\n"
02322 "\n"
02323 " -version : show the version information\n"
02324 "\n"
02325 " ---------------------------------------------------------------\n"
02326 " GERT_Reco2 options:\n"
02327 "\n"
02328 " -GERT_Reco2 : output a GERT_Reco2 script\n"
02329 "\n"
02330 " Create a script called 'GERT_Reco2', similar to the one\n"
02331 " that Ifile creates. This script may be run to create the\n"
02332 " AFNI datasets corresponding to the I-files.\n"
02333 "\n"
02334 " -gert_outdir OUTPUT_DIR : set output directory in GERT_Reco2\n"
02335 "\n"
02336 " e.g. -gert_outdir subject_A7\n"
02337 " e.g. -od subject_A7\n"
02338 " the default is '-gert_outdir afni'\n"
02339 "\n"
02340 " This will add '-od OUTPUT_DIR' to the @RenamePanga command\n"
02341 " in the GERT_Reco2 script, creating new datasets in the\n"
02342 " OUTPUT_DIR directory, instead of the 'afni' directory.\n"
02343 "\n"
02344 " -sp SLICE_PATTERN : set output slice pattern in GERT_Reco2\n"
02345 "\n"
02346 " e.g. -sp alt-z\n"
02347 " the default is 'alt+z'\n"
02348 "\n"
02349 " This options allows the user to alter the slice\n"
02350 " acquisition pattern in the GERT_Reco2 script.\n"
02351 "\n"
02352 " See 'to3d -help' for more information.\n"
02353 "\n"
02354 " ---------------------------------------------------------------\n"
02355 "\n"
02356 " Author: R. Reynolds - %s\n"
02357 "\n"
02358 " (many thanks to R. Birn)\n"
02359 "\n",
02360 prog, prog, prog, prog,
02361 prog, prog, prog, prog, prog, prog, prog, prog, prog,
02362 prog, prog, prog, prog, prog, prog, prog,
02363 IFM_VERSION
02364 );
02365
02366 return 0;
02367 }
02368 else if ( level == IFM_USE_HIST )
02369 {
02370 fputs( g_history, stdout );
02371 return 0;
02372 }
02373 else if ( level == IFM_USE_VERSION )
02374 {
02375 printf( "%s: %s, compile date: %s\n",
02376 prog, IFM_VERSION, __DATE__ );
02377 return 0;
02378 }
02379
02380 fprintf( stderr, "error: usage() called with illegal level <%d>\n", level );
02381
02382 return -1;
02383 }
02384
02385
02386
02387
02388
02389
02390 static void hf_signal( int signum )
02391 {
02392 switch ( signum )
02393 {
02394 default :
02395 fprintf( stderr, "\nError: received unknown signal, %d\n",
02396 signum );
02397 break;
02398
02399 case SIGINT :
02400 case SIGTERM :
02401 show_run_stats( &gS );
02402 break;
02403 }
02404
02405 exit(0);
02406 }
02407
02408
02409
02410
02411
02412
02413 static int set_volume_stats( param_t * p, stats_t * s, vol_t * v )
02414 {
02415 run_t * rp;
02416
02417 if ( v == NULL || v->seq_num < 0 || v->run < 0 )
02418 {
02419 fprintf( stderr, "failure: SVS - insufficient data\n\n" );
02420 idisp_hf_vol_t ( "-- VOLUME FAILURE INFO : ", v );
02421 }
02422
02423
02424 if ( s->nalloc == 0 )
02425 {
02426 s->runs = (run_t *)calloc( IFM_STAT_ALLOC, sizeof(run_t) );
02427 if ( s->runs == NULL )
02428 {
02429 fprintf( stderr, "failure: cannot allocate space for run info\n" );
02430 return -1;
02431 }
02432
02433
02434 s->slices = v->nim;
02435 s->z_first = v->z_first;
02436 s->z_last = v->z_last;
02437 s->z_delta = v->z_delta;
02438
02439 s->nalloc = IFM_STAT_ALLOC;
02440 s->nused = 0;
02441 s->nvols = gP.opts.nt;
02442
02443 if ( gD.level > 1 )
02444 fprintf( stderr, "\n-- svs: init alloc - vol %d, run %d, file %s\n",
02445 v->seq_num, v->run, v->first_file );
02446 }
02447
02448 if ( v->run >= s->nalloc )
02449 {
02450
02451 s->runs = (run_t *)realloc( s->runs, (v->run + IFM_STAT_ALLOC) *
02452 sizeof(run_t) );
02453 if ( s->runs == NULL )
02454 {
02455 fprintf( stderr, "failure: cannot realloc space for run info\n" );
02456 return -1;
02457 }
02458
02459 s->nalloc = v->run + IFM_STAT_ALLOC;
02460
02461
02462 memset( s->runs + s->nused, 0, (s->nalloc - s->nused)*sizeof(run_t) );
02463
02464 if ( gD.level > 1 )
02465 fprintf( stderr,
02466 "\n-- svs: realloc (%d entries) - vol %d, run %d, file %s\n",
02467 s->nalloc, v->seq_num, v->run, v->first_file );
02468
02469 }
02470
02471
02472
02473 rp = s->runs + v->run;
02474
02475 if ( s->nused < v->run+1 )
02476 s->nused = v->run+1;
02477
02478 if ( rp->volumes == 0 )
02479 strncpy( rp->f1name, v->first_file, IFM_MAX_FLEN );
02480
02481 rp->volumes = v->seq_num;
02482
02483
02484 if ( (p->opts.nt <= 0) && (s->nvols < v->seq_num) )
02485 s->nvols = v->seq_num;
02486
02487 if ( gD.level > 2 )
02488 fprintf( stderr, "\n-- svs: run %d, seq_num %d\n", v->run, v->seq_num );
02489
02490 return 0;
02491 }
02492
02493
02494
02495
02496
02497
02498
02499
02500 static int create_gert_script( stats_t * s, opts_t * opts )
02501 {
02502 FILE * fp;
02503 char * spat;
02504 char cdir[4], csuff[IFM_SUFFIX_LEN];
02505 int num_valid, c;
02506
02507
02508 spat = opts->sp ? opts->sp : IFM_SLICE_PAT;
02509
02510 for ( c = 0, num_valid = 0; c < s->nused; c++ )
02511 if ( s->runs[c].volumes > 0 )
02512 num_valid++;
02513
02514 if ( num_valid == 0 )
02515 {
02516 fprintf( stderr, "-- no runs to use for '%s'\n", IFM_GERT_SCRIPT );
02517 return 0;
02518 }
02519
02520 if ( (fp = fopen( IFM_GERT_SCRIPT, "w" )) == NULL )
02521 {
02522 fprintf( stderr, "failure: cannot open '%s' for writing, "
02523 "check permissions\n", IFM_GERT_SCRIPT );
02524 return -1;
02525 }
02526
02527
02528 fprintf( fp,
02529 "#!/bin/tcsh\n"
02530 "\n"
02531 "# This script was automatically generated by '%s'.\n"
02532 "# The script format was, uh, borrowed from Ziad's Ifile.c.\n"
02533 "#\n"
02534 "# Please modify the following options for your own evil uses.\n"
02535 "\n"
02536 "set OutlierCheck = '-oc' # use '' to skip outlier check\n"
02537 "set OutPrefix = 'OutBrick' # prefix for datasets\n"
02538 "set OutputDir = '-od %s' # where to put output datasets\n"
02539 "\n"
02540 "\n",
02541 IFM_PROG_NAME,
02542 opts->gert_outdir ? opts->gert_outdir : "afni"
02543 );
02544
02545 for ( c = 0; c < s->nused; c++ )
02546 if ( s->runs[c].volumes > 0 )
02547 {
02548 if ( path_to_dir_n_suffix(cdir, csuff, s->runs[c].f1name) < 0 )
02549 {
02550 fclose( fp );
02551 return -1;
02552 }
02553
02554 fprintf( fp, "@RenamePanga %s %s %d %d $OutPrefix "
02555 "-sp %s $OutlierCheck $OutputDir\n",
02556 cdir, csuff, s->slices, s->runs[c].volumes, spat );
02557 }
02558
02559 fputc( '\n', fp );
02560 fclose( fp );
02561
02562
02563 system( "chmod u+x " IFM_GERT_SCRIPT );
02564
02565 return 0;
02566 }
02567
02568
02569
02570
02571
02572
02573
02574 static int show_run_stats( stats_t * s )
02575 {
02576 int c;
02577
02578 if ( s == NULL )
02579 {
02580 fprintf( stderr, "failure, SRS - no stats struct!\n" );
02581 return -1;
02582 }
02583
02584 if ( s->nalloc <= 0 || s->nused <= 0 )
02585 return 0;
02586
02587 printf( "\n\n"
02588 "final run statistics:\n"
02589 " volume info :\n"
02590 " slices : %d\n"
02591 " z_first : %.4f\n"
02592 " z_last : %.4f\n"
02593 " z_delta : %.4f\n"
02594 "\n",
02595 s->slices, s->z_first, s->z_last, s->z_delta );
02596
02597 for ( c = 0; c < s->nused; c++ )
02598 {
02599 if ( s->runs[c].volumes > 0 )
02600 printf( " run #%4d : volumes = %3d, first file = %s\n",
02601 c, s->runs[c].volumes, s->runs[c].f1name );
02602 }
02603
02604 putchar( '\n' );
02605
02606 if ( gP.opts.gert_reco )
02607 (void)create_gert_script( s, &gP.opts );
02608
02609 fflush( stdout );
02610
02611 return 0;
02612 }
02613
02614
02615
02616
02617
02618
02619 static int nap_time_from_tr( float tr )
02620 {
02621 float tr2 = 2 * tr;
02622
02623 if ( tr2 < 1 )
02624 return 1;
02625
02626 if ( tr2 > 10 )
02627 return 10;
02628
02629 return( (int)(tr2 + 0.9) );
02630 }
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644 static int find_next_zoff( param_t * p, int start, float zoff )
02645 {
02646 int count;
02647
02648 if ( (p == NULL) || (start < 0) )
02649 return -2;
02650
02651 if ( start > p->nused )
02652 return -1;
02653
02654 for ( count = start; count <= p->nused; count++ )
02655 if ( fabs( zoff - p->flist[count].geh.zoff ) < IFM_EPSILON )
02656 return count;
02657
02658 return -1;
02659 }
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680 static int check_stalled_run ( int run, int seq_num, int naps, int nap_time )
02681 {
02682 static int func_failure = 0;
02683 static int prev_run = -1;
02684 static int prev_seq = -1;
02685
02686 if ( func_failure != 0 )
02687 return 0;
02688
02689 if ( ( run < 1 ) || ( seq_num < 1 ) || ( naps <= IFM_MAX_RUN_NAPS ) )
02690 return 0;
02691
02692
02693 if ( (((gS.nused + 1) < run) || (gS.runs[run].volumes < seq_num)) &&
02694 ( func_failure == 0 ) )
02695 {
02696 fprintf( stderr, "** warning: CSR - stats inconsistancy!\n" );
02697 func_failure = 1;
02698
02699 return -1;
02700 }
02701
02702 if ( seq_num < gS.nvols )
02703 {
02704
02705 if ( (run != prev_run) || (seq_num != prev_seq) )
02706 {
02707 fprintf( stderr, "\007\n"
02708 "****************************************************\n"
02709 "Warning: run seems to be stalled\n"
02710 "\n"
02711 " run : %d\n"
02712 " TRs completed : %d (of %d)\n"
02713 " approximate idle time : %d seconds\n"
02714 " first file of this run : %s\n"
02715 "****************************************************\n",
02716 run, seq_num, gS.nvols,
02717 naps*nap_time, gS.runs[run].f1name );
02718
02719 prev_run = run;
02720 prev_seq = seq_num;
02721
02722 return 2;
02723 }
02724 }
02725
02726 else if ( (run != prev_run) || (seq_num != prev_seq) )
02727 {
02728
02729 prev_run = run;
02730 prev_seq = seq_num;
02731
02732 return 1;
02733 }
02734
02735 return 0;
02736 }
02737
02738
02739
02740
02741
02742 static unsigned long l_THD_filesize( char * pathname )
02743 {
02744 static struct stat buf ; int ii ;
02745
02746 if( pathname == NULL ) return -1 ;
02747 ii = stat( pathname , &buf ) ; if( ii != 0 ) return -1 ;
02748
02749 return buf.st_size ;
02750 }
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760 static int check_im_store_space( im_store_t * is, int num_images )
02761 {
02762 if ( (is == NULL) || (num_images <= 0) )
02763 {
02764 fprintf( stderr, "** CISS: invalid parameters (%p,%d)\n",
02765 is, num_images );
02766 return -1;
02767 }
02768
02769 if ( is->ary_len >= num_images )
02770 return 0;
02771
02772
02773
02774 if ( gD.level > 2 )
02775 fprintf( stderr, "++ allocating %d image pointers (was %d)\n",
02776 num_images, is->ary_len );
02777
02778 is->im_ary = realloc(is->im_ary, num_images * sizeof(void *));
02779
02780 if ( is->im_ary == NULL )
02781 {
02782 fprintf( stderr, "** failure: cannot allocate %d image pointers\n",
02783 num_images );
02784 return -1;
02785 }
02786
02787 is->ary_len = num_images;
02788
02789 return 1;
02790 }
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800 static int alloc_x_im( im_store_t * is, int bytes )
02801 {
02802 if ( (is == NULL) || (bytes <= 0) )
02803 {
02804 fprintf( stderr, "** bad params to AXI (%p,%d)\n", is, bytes );
02805 return -1;
02806 }
02807
02808 is->im_size = bytes;
02809
02810 if ( (is->x_im = malloc( bytes )) == NULL )
02811 {
02812 fprintf( stderr, "** AXI: failed to malloc %d bytes for x_im\n",
02813 bytes );
02814 return -1;
02815 }
02816
02817 if ( gD.level > 1 )
02818 fprintf( stderr, "++ allocating %d bytes for is->x_im\n", bytes );
02819
02820 return 0;
02821 }
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833
02834 static int check_im_byte_order( int * order, vol_t * v, param_t * p )
02835 {
02836 int one = 1;
02837
02838 if ( (order == NULL) || (v == NULL) || (p == NULL) )
02839 {
02840 fprintf( stderr, "** invalid paramters to CIBO (%p,%p,%p)\n",
02841 order, v, p );
02842 return -1;
02843 }
02844
02845
02846 *order = (*(char *)&one == 1) ? LSB_FIRST : MSB_FIRST;
02847
02848 if ( gD.level > 1 )
02849 fprintf( stderr, "-- system order is %s, ",
02850 (*order == MSB_FIRST) ? "MSB_FIRST" : "LSB_FIRST" );
02851
02852
02853 if ( p->flist[v->fl_1].gex.swap ^ p->opts.rev_bo )
02854 *order = LSB_FIRST + MSB_FIRST - *order;
02855
02856 if ( gD.level > 1 )
02857 fprintf( stderr, "image order is %s\n",
02858 (*order == MSB_FIRST) ? "MSB_FIRST" : "LSB_FIRST" );
02859
02860 return 0;
02861 }
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876 static int complete_orients_str( vol_t * v, param_t * p )
02877 {
02878 int kk;
02879
02880 if ( (v == NULL) || (p == NULL) )
02881 {
02882 fprintf( stderr, "** invalid paramters to COS (%p,%p)\n", v, p );
02883 return -1;
02884 }
02885
02886 kk = p->flist[v->fl_1].gex.kk;
02887
02888 switch( kk )
02889 {
02890 case 1:
02891 if ( v->z_delta > 0 )
02892 {
02893 v->geh.orients[4] = 'L';
02894 v->geh.orients[5] = 'R';
02895 }
02896 else
02897 {
02898 v->geh.orients[4] = 'R';
02899 v->geh.orients[5] = 'L';
02900 }
02901 break;
02902
02903 case 2:
02904 if ( v->z_delta > 0 )
02905 {
02906 v->geh.orients[4] = 'P';
02907 v->geh.orients[5] = 'A';
02908 }
02909 else
02910 {
02911 v->geh.orients[4] = 'A';
02912 v->geh.orients[5] = 'P';
02913 }
02914 break;
02915
02916 case 3:
02917 if ( v->z_delta > 0 )
02918 {
02919 v->geh.orients[4] = 'I';
02920 v->geh.orients[5] = 'S';
02921 }
02922 else
02923 {
02924 v->geh.orients[4] = 'S';
02925 v->geh.orients[5] = 'I';
02926 }
02927 break;
02928
02929 default:
02930 {
02931 fprintf(stderr, "** COS failure: kk (%d) out of [1,3] range\n", kk);
02932 return -1;
02933 }
02934 }
02935
02936 v->geh.orients[6] = '\0';
02937
02938 return 0;
02939 }
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949 static int find_fl_file_index( param_t * p, char * file )
02950 {
02951 char ** nlp;
02952 int index;
02953
02954 if ( (p == NULL) || (file == NULL) )
02955 return 0;
02956
02957 for ( index = 0, nlp = p->fnames; index < p->nfiles; index++, nlp++ )
02958 if ( ! strcmp( *nlp, file ) )
02959 return index;
02960
02961 return -1;
02962 }
02963
02964
02965
02966
02967
02968 static int str_char_count( char * str, int len, char target )
02969 {
02970 char * cp;
02971 char * last = str + len;
02972 int num = 0;
02973
02974 if ( (str == NULL) || (len <= 0) )
02975 return 0;
02976
02977 for ( cp = str; cp < last; cp++ )
02978 if ( *cp == target )
02979 num++;
02980
02981 return num;
02982 }
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996 static int path_to_dir_n_suffix( char * dir, char * suff, char * path )
02997 {
02998 char * cp, *cp2;
02999
03000 if ( (dir == NULL) || (suff == NULL) || (path == NULL) )
03001 {
03002 fprintf( stderr, "failure: PTDNS - invalid params (%p,%p,%p)\n",
03003 dir, suff, path );
03004 return -1;
03005 }
03006
03007
03008 for ( cp = path + strlen(path) - 1; (*cp != '.') && (cp > path); cp-- )
03009 ;
03010
03011 if ( *cp != '.' )
03012 {
03013 fprintf( stderr, "failure: cannot find suffix in '%s'\n", path );
03014 return -1;
03015 }
03016 else if ( strlen( cp ) > IFM_SUFFIX_LEN )
03017 {
03018 fprintf( stderr, "failure: suffix too long in '%s'\n", path );
03019 return -1;
03020 }
03021
03022 strcpy( suff, cp+1 );
03023
03024
03025 for ( cp2 = suff; (*cp2 != '\0') && isdigit(*cp2); cp2++ )
03026 ;
03027
03028 if ( *cp2 != '\0' )
03029 {
03030 fprintf( stderr, "failure: suffix not integer in '%s'\n", path );
03031 return -1;
03032 }
03033
03034
03035 cp -= 5;
03036 if ( ( cp < path ) ||
03037 ( ! isdigit( cp[0] ) ) ||
03038 ( ! isdigit( cp[1] ) ) ||
03039 ( ! isdigit( cp[2] ) ) ||
03040 ( cp[3] != '/' ) ||
03041 ( cp[4] != 'I' ) )
03042 {
03043 fprintf( stderr, "failure: PTDNS - ill-formed path '%s'\n", path );
03044 return -1;
03045 }
03046
03047
03048 strncpy( dir, cp, 3 );
03049 dir[3] = '\0';
03050
03051 return 0;
03052 }
03053
03054
03055
03056
03057
03058
03059
03060
03061
03062 static int add_to_string_list( string_list * list, char * str )
03063 {
03064 if ( !list || !str )
03065 return -1;
03066
03067
03068 if ( list->nalloc == 0 || (list->nalloc <= list->nused) )
03069 {
03070 list->nalloc += 10;
03071 list->str = (char **)realloc(list->str, list->nalloc*sizeof(char *));
03072 if ( !list->str )
03073 {
03074 fprintf(stderr,"** failed to allocate for %d (char *)s\n",
03075 list->nalloc);
03076 return -1;
03077 }
03078 }
03079
03080 list->str[list->nused] = str;
03081 list->nused++;
03082
03083 return 0;
03084 }
03085
03086
03087
03088
03089
03090
03091 static int empty_string_list( string_list * list, int free_mem )
03092 {
03093 if ( list->str && free_mem )
03094 free( list->str );
03095
03096 list->str = NULL;
03097 list->nalloc = 0;
03098 list->nused = 0;
03099
03100 return 0;
03101 }
03102