00001
00002 static char g_history[] =
00003 "----------------------------------------------------------------------\n"
00004 " history:\n"
00005 "\n"
00006 " 1.0 Jul 5, 2005 [rickr] - initial release\n"
00007 " 1.1 Jul 13, 2005 [rickr] - process run of fewer than 3 slices\n"
00008 " 1.2 Jul 22, 2005 [rickr] - use IOCHAN_CLOSENOW() in realtime.c\n"
00009 " 1.3 Jul 25, 2005 [rickr] - force tcp close for multiple term signals\n"
00010 " 2.0 Jul 29, 2005 [rickr] - DICOM file organizer\n"
00011 " - add -dicom_org option, to try to organize the image files\n"
00012 " - enable GERT_Reco option for DICOM files\n"
00013 "----------------------------------------------------------------------\n";
00014
00015 #define DIMON_VERSION "version 2.0 (August 01, 2005)"
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 #include <stdio.h>
00066 #include <ctype.h>
00067 #include <dirent.h>
00068 #include <errno.h>
00069 #include <math.h>
00070 #include <signal.h>
00071 #include <stdlib.h>
00072 #include <string.h>
00073 #include <sys/types.h>
00074 #include <sys/stat.h>
00075 #include <unistd.h>
00076
00077 #define MAIN
00078 #define IFM_PROG_NAME "Dimon"
00079
00080 #include "Imon.h"
00081 #include "l_mcw_glob.h"
00082 #include "thd_iochan.h"
00083 #include "realtime.h"
00084 #include "mri_image.h"
00085 #include "dbtrace.h"
00086
00087 extern char DI_MRL_orients[8];
00088 extern float DI_MRL_tr;
00089
00090 extern struct dimon_stuff_t { int study, series, image; } gr_dimon_stuff;
00091
00092 int compare_finfo( const void * v0, const void * v1 );
00093 static int dicom_order_files( param_t * p );
00094 extern MRI_IMAGE * r_mri_read_dicom( char *fname, int debug, void ** data );
00095 static int read_dicom_image( char *pathname, finfo_t *fp, int get_data);
00096
00097
00098
00099
00100 static int add_to_string_list ( string_list * list, char * str );
00101 static int alloc_x_im ( im_store_t * is, int bytes );
00102 static int check_error ( int * retry, float tr, char * note );
00103 static int check_im_byte_order ( int * order, vol_t * v, param_t * p );
00104 static int check_im_store_space( im_store_t * is, int num_images );
00105 static int check_stalled_run ( int run, int seq_num, int naps, int nap_time );
00106 static int complete_orients_str( vol_t * v, param_t * p );
00107 static int create_gert_script ( stats_t * s, param_t * p );
00108 static int create_gert_reco ( stats_t * s, opts_t * opts );
00109 static int create_gert_dicom ( stats_t * s, param_t * p );
00110 static int dir_expansion_form ( char * sin, char ** sexp );
00111 static int disp_ftype ( char * info, int ftype );
00112 static int empty_string_list ( string_list * list, int free_mem );
00113 static int find_first_volume ( vol_t * v, param_t * p, ART_comm * ac );
00114 static int find_fl_file_index ( param_t * p );
00115 static int find_more_volumes ( vol_t * v, param_t * p, ART_comm * ac );
00116 static int find_next_zoff ( param_t * p, int start, float zoff );
00117 static int init_extras ( param_t * p, ART_comm * ac );
00118 static int init_options ( param_t * p, ART_comm * a, int argc,
00119 char * argv[] );
00120 static int nap_time_from_tr ( float tr );
00121 static int path_to_dir_n_suffix( char * dir, char * suff, char * path );
00122 static int read_ge_files ( param_t * p, int start, int max );
00123 static int read_ge_image ( char * pathname, finfo_t * fp,
00124 int get_image, int need_memory );
00125 static int scan_ge_files ( param_t * p, int next, int nfiles );
00126 static int set_nice_level ( int level );
00127 static int set_volume_stats ( param_t * p, stats_t * s, vol_t * v );
00128 static int show_run_stats ( stats_t * s );
00129 static int str_char_count ( char * str, int len, char target );
00130 static int swap_4 ( void * ptr );
00131
00132 static void hf_signal ( int signum );
00133
00134
00135 int check_one_volume (param_t *p, int start, int *fl_start, int bound,
00136 int state, int * r_first, int * r_last,
00137 float * r_delta);
00138 static int volume_match ( vol_t * vin, vol_t * vout, param_t * p, int start );
00139 static int volume_search ( vol_t * V, param_t * p, int start, int maxsl,
00140 int * fl_start, int * state );
00141
00142
00143 static int idisp_opts_t ( char * info, opts_t * opt );
00144 static int idisp_param_t ( char * info, param_t * p );
00145 static int idisp_vol_t ( char * info, vol_t * v );
00146 static int idisp_ge_extras ( char * info, ge_extras * E );
00147 static int idisp_ge_header_info ( char * info, ge_header_info * I );
00148 static int idisp_im_store_t ( char * info, im_store_t * is );
00149
00150 static int usage ( char * prog, int level );
00151
00152
00153 unsigned long l_THD_filesize( char * pathname );
00154
00155
00156
00157
00158
00159
00160 IFM_debug gD;
00161 param_t gP;
00162 stats_t gS;
00163 ART_comm gAC;
00164
00165
00166 int main( int argc, char * argv[] )
00167 {
00168 ART_comm * ac = &gAC;
00169 param_t * p = &gP;
00170 vol_t baseV;
00171 int ret_val;
00172
00173
00174 if ( (ret_val = init_options( p, ac, argc, argv )) != 0 )
00175 return ret_val;
00176
00177 if ( (ret_val = init_extras( p, ac )) != 0 )
00178 return ret_val;
00179
00180 if ( (ret_val = find_first_volume( &baseV, p, ac )) != 0 )
00181 return ret_val;
00182
00183 if ( (ret_val = find_more_volumes( &baseV, p, ac )) != 0 )
00184 return ret_val;
00185
00186 return 0;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 static int find_first_volume( vol_t * v, param_t * p, ART_comm * ac )
00201 {
00202 int max_im_alloc = IFM_MAX_IM_ALLOC;
00203 int ret_val;
00204 int sleep_secs = -1;
00205 int vs_state = 0;
00206 int fl_start = 0;
00207
00208 if ( gD.level > 0 )
00209 fprintf( stderr, "-- scanning for first volume\n" );
00210
00211 ret_val = 0;
00212 while ( ret_val == 0 )
00213 {
00214 ret_val = read_ge_files( p, fl_start, max_im_alloc );
00215
00216 if ( ret_val > 0 )
00217 {
00218 ret_val = volume_search( v, p, 0, 0, &fl_start, &vs_state );
00219
00220
00221 if ( ret_val == -1 ) ret_val = 0;
00222
00223
00224
00225
00226 if ( (ret_val == 0) && (p->nused > (max_im_alloc / 2)) )
00227 max_im_alloc *= 2;
00228 }
00229
00230 if ( ret_val == 0 )
00231 {
00232 if ( gD.level > 0 ) fprintf( stderr, "." );
00233
00234
00235 if( sleep_secs < 0 && p->nused > 0 )
00236 sleep_secs = nap_time_from_tr(p->flist->geh.tr);
00237
00238 if( sleep_secs < 0 ) sleep( 4 );
00239 else sleep(sleep_secs);
00240 }
00241 else if ( ret_val > 0 )
00242 {
00243 if ( gD.level > 0 )
00244 {
00245 fprintf( stderr, "\n-- first volume found\n" );
00246 if ( gD.level > 1 )
00247 {
00248 idisp_vol_t( "+d first volume : ", v );
00249 idisp_param_t( "-d first vol - new params : ", p );
00250 disp_ftype("-d ftype: ", p->ftype);
00251 }
00252 }
00253
00254
00255 if ( p->nalloc < (4 * v->nim) )
00256 {
00257 p->nalloc = 4 * v->nim;
00258 p->flist = (finfo_t *)realloc( p->flist,
00259 p->nalloc*sizeof(finfo_t) );
00260 if ( p->flist == NULL )
00261 {
00262 fprintf( stderr, "** FFV: failure to allocate %d finfo_t "
00263 "structs!\n", p->nalloc );
00264 return -1;
00265 }
00266
00267 if ( gD.level > 1 )
00268 idisp_param_t( "++ final realloc of flist : ", p );
00269 }
00270
00271
00272 if ( complete_orients_str( v, p ) < 0 )
00273 return -1;
00274
00275
00276 if ( check_im_byte_order( &ac->byte_order, v, p ) < 0 )
00277 return -1;
00278
00279
00280 if ( ac->state == ART_STATE_TO_OPEN )
00281 ART_open_afni_link( ac, 5, 0, gD.level );
00282
00283 if ( ac->state == ART_STATE_TO_SEND_CTRL )
00284 ART_send_control_info( ac, v, gD.level );
00285
00286 if ( ac->state == ART_STATE_IN_USE )
00287 ART_send_volume( ac, v, gD.level );
00288
00289 if ( gD.level > 1 )
00290 {
00291 ART_idisp_ART_comm( "-- first vol ", ac );
00292 idisp_im_store_t( "-- first vol ", &p->im_store );
00293 }
00294 }
00295 else
00296 return ret_val;
00297 }
00298
00299 if ( ret_val > 0 )
00300 return 0;
00301 else
00302 return ret_val;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 static int find_more_volumes( vol_t * v0, param_t * p, ART_comm * ac )
00316 {
00317 vol_t vn;
00318 int ret_val, done;
00319 int run, seq_num, next_im;
00320 int fl_index;
00321 int naps;
00322 int nap_time;
00323
00324 if ( v0 == NULL || p == NULL )
00325 {
00326 fprintf( stderr, "error: IFM:FMV() lacking parameters\n" );
00327 return -1;
00328 }
00329
00330 done = 0;
00331 naps = 0;
00332
00333 run = v0->run;
00334 seq_num = v0->seq_num = 1;
00335 fl_index = v0->fn_n + 1;
00336 next_im = v0->fn_n + 1;
00337
00338 nap_time = nap_time_from_tr( v0->geh.tr );
00339
00340 if ( gD.level > 0 )
00341 {
00342 fprintf( stderr, "-- scanning for additional volumes...\n" );
00343 fprintf( stderr, "-- run %d: %d ", run, seq_num );
00344 }
00345
00346
00347 signal( SIGHUP, hf_signal );
00348 signal( SIGINT, hf_signal );
00349 signal( SIGQUIT, hf_signal );
00350 signal( SIGTRAP, hf_signal );
00351 signal( SIGABRT, hf_signal );
00352 signal( SIGTERM, hf_signal );
00353 signal( SIGSEGV, hf_signal );
00354
00355 if ( set_volume_stats( p, &gS, v0 ) )
00356 return -1;
00357
00358 while ( ! done )
00359 {
00360
00361 ret_val = 1;
00362 while ( (ret_val == 1) || (ret_val == -1) )
00363 {
00364 ret_val = volume_match( v0, &vn, p, fl_index );
00365
00366 if ( ret_val < -1 )
00367 return ret_val;
00368
00369 if ( (ret_val == 1) || (ret_val == -1) )
00370 {
00371 if ( gD.level > 2 )
00372 idisp_vol_t( "-- new volume: ", &vn );
00373
00374 fl_index += vn.nim;
00375 next_im = vn.fn_n + 1;
00376
00377 if ( vn.run != run )
00378 {
00379
00380 if ( ac->state == ART_STATE_IN_USE )
00381 ART_send_end_of_run( ac, run, seq_num, gD.level );
00382
00383 run = vn.run;
00384 seq_num = 1;
00385
00386 if ( gD.level > 0 )
00387 fprintf( stderr, "\n-- run %d: %d ", run, seq_num );
00388 }
00389 else
00390 {
00391 seq_num++;
00392
00393 if ( gD.level > 0 )
00394 fprintf( stderr, "%d ", seq_num );
00395 }
00396
00397 vn.seq_num = seq_num;
00398
00399 if ( set_volume_stats( p, &gS, &vn ) )
00400 return -1;
00401
00402 if ( complete_orients_str( &vn, p ) < 0 )
00403 return -1;
00404
00405 if ( ac->state == ART_STATE_TO_SEND_CTRL )
00406 ART_send_control_info( ac, &vn, gD.level );
00407
00408
00409 if ( (ac->state == ART_STATE_IN_USE) && (ret_val == 1) )
00410 ART_send_volume( ac, &vn, gD.level );
00411
00412 naps = 0;
00413
00414 if( p->opts.pause > 0 ) iochan_sleep(p->opts.pause);
00415 }
00416 }
00417
00418
00419
00420 ret_val = read_ge_files( p, next_im, p->nalloc );
00421 fl_index = 0;
00422
00423 while ( (ret_val >= 0 ) &&
00424 (ret_val < v0->nim) )
00425 {
00426 if ( naps > 0 )
00427 {
00428 if ( p->opts.quit )
00429 {
00430 if ( ac->state == ART_STATE_IN_USE )
00431 ART_send_end_of_run( ac, run, seq_num, gD.level );
00432
00433 show_run_stats( &gS );
00434 return 0;
00435 }
00436
00437
00438 if ( check_stalled_run( run, seq_num, naps, nap_time ) > 0 )
00439 if ( ac->state == ART_STATE_IN_USE )
00440 ART_send_end_of_run( ac, run, seq_num, gD.level );
00441
00442 if ( gD.level > 0 )
00443 fprintf( stderr, ". " );
00444 }
00445
00446 sleep( nap_time );
00447 naps ++;
00448
00449 ret_val = read_ge_files( p, next_im, p->nalloc );
00450 }
00451
00452 if ( ret_val < 0 )
00453 {
00454 fprintf( stderr, "\n** failure: IFM:RGF fatal error\n" );
00455 return -1;
00456 }
00457 }
00458
00459 return 0;
00460 }
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 static int volume_search(
00480 vol_t * V,
00481 param_t * p,
00482 int start,
00483 int maxsl,
00484 int * fl_start,
00485 int * state )
00486 {
00487 float delta;
00488 int bound;
00489 static int prev_bound = -1;
00490 int first = start;
00491 int last;
00492 int rv;
00493
00494 if ( V == NULL || p == NULL || p->flist == NULL || start < 0 )
00495 {
00496 fprintf( stderr, "failure: FNV: bad parameter data\n" );
00497 return -2;
00498 }
00499
00500
00501 if ( (maxsl <= 0) || ((maxsl + first) >= p->nused) )
00502 bound = p->nused;
00503 else
00504 bound = first + maxsl;
00505
00506 if ( ( bound-first < 1) ||
00507 ((bound-first < 4) && !p->opts.use_dicom) )
00508 return 0;
00509
00510
00511 if ( *state == 1 && bound == prev_bound ) *state = 2;
00512 else *state = 1;
00513 prev_bound = bound;
00514
00515 rv = check_one_volume(p,start,fl_start,bound,*state, &first,&last,&delta);
00516
00517 if ( rv == 1 )
00518 {
00519
00520
00521 V->geh = p->flist[first].geh;
00522 V->gex = p->flist[first].gex;
00523 V->nim = last - first + 1;
00524 V->fl_1 = first;
00525 V->fn_1 = p->flist[first].index;
00526 V->fn_n = p->flist[last].index;
00527 strncpy( V->first_file, p->fnames[V->fn_1], IFM_MAX_FLEN );
00528 strncpy( V->last_file, p->fnames[V->fn_n], IFM_MAX_FLEN );
00529 V->z_first = p->flist[first].geh.zoff;
00530 V->z_last = p->flist[last].geh.zoff;
00531 V->z_delta = delta;
00532 V->seq_num = -1;
00533 V->run = V->geh.uv17;
00534
00535 return 1;
00536 }
00537 else if ( rv == 0 )
00538 return 0;
00539 else if ( rv == -1 )
00540 {
00541
00542
00543
00544 fprintf( stderr, "\n"
00545 "*************************************************\n"
00546 "Error: missing slice(s) in first volume!\n"
00547 " attempting to re-start at file: %s\n"
00548 "*************************************************\n",
00549 p->fnames[p->flist[last+1].index] );
00550 *fl_start = p->flist[last+1].index;
00551 }
00552 else
00553 {
00554
00555 int testc;
00556 for ( testc = last; testc < bound; testc++ )
00557 if ( abs( p->flist[first].geh.zoff -
00558 p->flist[testc].geh.zoff ) < IFM_EPSILON )
00559 {
00560
00561
00562 fprintf( stderr, "\n"
00563 "*************************************************\n"
00564 "Error: missing slice in first volume!\n"
00565 " detected at file: %s\n"
00566 " re-starting at file: %s\n"
00567 "*************************************************\n",
00568 p->fnames[p->flist[last+1].index],
00569 p->fnames[p->flist[testc].index] );
00570
00571
00572 *fl_start = p->flist[testc].index;
00573
00574 return -1;
00575 }
00576
00577
00578 return 0;
00579 }
00580
00581 return -1;
00582 }
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 int check_one_volume(param_t *p, int start, int *fl_start, int bound, int state,
00596 int * r_first, int * r_last, float * r_delta)
00597 {
00598 finfo_t * fp;
00599 float delta, z_orig, prev_z, dz;
00600 int run0, run1, first, next, last;
00601
00602 if( bound <= start )
00603 {
00604 fprintf(stderr,"error: COV: bad bound, start (%d,%d)\n", bound, start);
00605 return -2;
00606 }
00607
00608
00609 if( state == 2 && (bound-start) < 3 )
00610 {
00611 if( gD.level > 1 )
00612 fprintf(stderr,"-d stall after only %d slices\n", bound-start);
00613 *r_first = start;
00614 if( (bound-start) == 1 )
00615 {
00616 *r_last = start;
00617 *r_delta = 1.0;
00618 }
00619 else
00620 {
00621 delta = p->flist[start+1].geh.zoff - p->flist[start].geh.zoff;
00622 if ( fabs(delta) < IFM_EPSILON )
00623 {
00624 *r_last = start;
00625 *r_delta = 1.0;
00626 }
00627 else
00628 {
00629 *r_last = start+1;
00630 *r_delta = delta;
00631 }
00632 }
00633 return 1;
00634 }
00635 else if ( bound-start < 3 )
00636 return 0;
00637
00638 first = start;
00639 delta = p->flist[first+1].geh.zoff - p->flist[first].geh.zoff;
00640
00641 run0 = p->flist[first ].geh.uv17;
00642 run1 = p->flist[first+1].geh.uv17;
00643
00644
00645 if ( (fabs(delta) < IFM_EPSILON) || (run1 != run0) )
00646 {
00647
00648 if ( p->opts.use_dicom )
00649 {
00650 if( gD.level > 1 ) fprintf(stderr,"+d found single slice volume\n");
00651 *r_first = *r_last = first;
00652 *r_delta = 1.0;
00653 return 1;
00654 }
00655
00656 if ( gD.level > 1 )
00657 fprintf( stderr, "-- skipping single slice volume <%s>\n",
00658 p->fnames[p->flist[first].index] );
00659 first++;
00660 delta = p->flist[first+1].geh.zoff - p->flist[first].geh.zoff;
00661 run0 = run1;
00662
00663 if ( fabs(delta) < IFM_EPSILON )
00664 {
00665 fprintf( stderr, "Error: 3 slices with 0 delta, beginning with"
00666 "file <%s>\n", p->fnames[p->flist[start].index] );
00667 *fl_start = p->flist[start+2].index;
00668 return -1;
00669 }
00670 }
00671
00672 fp = p->flist + first;
00673 z_orig = fp->geh.zoff;
00674
00675
00676 fp++;
00677 prev_z = fp->geh.zoff;
00678 run1 = fp->geh.uv17;
00679 dz = delta;
00680
00681
00682 next = first + 2;
00683 while ( (next < bound) && (fabs(dz - delta) < IFM_EPSILON) &&
00684 (run1 == run0) )
00685 {
00686 fp++;
00687
00688 dz = fp->geh.zoff - prev_z;
00689 run1 = fp->geh.uv17;
00690 prev_z = fp->geh.zoff;
00691
00692 next++;
00693 }
00694
00695
00696
00697 if ( (fabs(dz - delta) > IFM_EPSILON) || (run1 != run0) ) last = next - 2;
00698 else last = next - 1;
00699
00700
00701 *r_first = first;
00702 *r_last = last;
00703 *r_delta = delta;
00704
00705 if( gD.level > 1 )
00706 fprintf(stderr,"+d cov: returning first, last, delta = %d, %d, %f\n",
00707 first, last, delta);
00708
00709
00710 if ( fabs(fp->geh.zoff - p->flist[first].geh.zoff) < IFM_EPSILON )
00711 {
00712 if ( gD.level > 1 )
00713 fprintf(stderr,"+d found first slice of second volume\n");
00714 return 1;
00715 }
00716
00717
00718
00719 if ( ( state == 2 && fabs(dz-delta)<IFM_EPSILON) && run1 == run0 )
00720 {
00721 if ( gD.level > 1 )
00722 fprintf(stderr,"+d no new data after finding sufficient slices\n"
00723 " --> assuming completed single volume\n");
00724 return 1;
00725 }
00726
00727 if ( (fabs(dz - delta) < IFM_EPSILON) && (run1 == run0) )
00728 return 0;
00729 if ( dz * delta < 0.0 ) return -1;
00730
00731
00732 return -2;
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747 static int volume_match( vol_t * vin, vol_t * vout, param_t * p, int start )
00748 {
00749 static int retry = 1;
00750 finfo_t * fp;
00751 finfo_t * fp_test;
00752 float z;
00753 int count, next_start = -1;
00754 int missing = 0;
00755
00756 if ( vin == NULL || vout == NULL ||
00757 p == NULL || p->flist == NULL || start < 0 )
00758 {
00759 fprintf( stderr, "failure: FMV: bad parameter data\n" );
00760 return -2;
00761 }
00762
00763 if ( (p->nused - start) < vin->nim )
00764 return 0;
00765
00766
00767
00768 fp = p->flist+start;
00769 for ( count = 0; count < vin->nim - 1; count++ )
00770 {
00771 z = vin->z_first + count * vin->z_delta;
00772
00773 if ( fabs( z - fp->geh.zoff ) > IFM_EPSILON )
00774 {
00775
00776
00777 fp_test = fp + 1;
00778 if ( fabs( z + vin->z_delta - fp_test->geh.zoff ) < IFM_EPSILON )
00779 {
00780
00781 if ( !check_error(&retry, vin->geh.tr, "slice out of order") )
00782 return 0;
00783
00784
00785
00786
00787 IFM_BIG_ERROR_MESG( "slice out of order!",
00788 p->fnames[fp->index], z, fp->geh.zoff,
00789 fp->geh.uv17, count + 1, vin->nim );
00790 }
00791 else if ( fabs(z + vin->z_delta - fp->geh.zoff) < IFM_EPSILON )
00792 {
00793
00794
00795
00796 if ( !check_error(&retry, vin->geh.tr, "slice missing") )
00797 return 0;
00798
00799
00800 missing++;
00801
00802 IFM_BIG_ERROR_MESG( "slice missing!",
00803 p->fnames[fp->index], z, fp->geh.zoff,
00804 fp->geh.uv17, count + 1, vin->nim );
00805
00806 count++;
00807 }
00808 else
00809 {
00810
00811 next_start = find_next_zoff( p, start+count, vin->z_first );
00812
00813 if ( next_start < 0 )
00814 return 0;
00815 else
00816 {
00817
00818 if ( !check_error(&retry, vin->geh.tr, "vol toasted") )
00819 return 0;
00820
00821 IFM_BIG_ERROR_MESG( "volume severely toasted!",
00822 p->fnames[fp->index], z, fp->geh.zoff,
00823 fp->geh.uv17, count + 1, vin->nim );
00824
00825 break;
00826 }
00827 }
00828 }
00829
00830 fp++;
00831 }
00832
00833 z = vin->z_first + count * vin->z_delta;
00834
00835 if ( count >= vin->nim )
00836 next_start = start + vin->nim - missing;
00837 else if ( (next_start < 0) && (fabs( z - fp->geh.zoff ) > IFM_EPSILON) )
00838 {
00839
00840 if ( (p->nused - start) <= vin->nim )
00841 return 0;
00842
00843 fp_test = fp + 1;
00844 if ( fabs( vin->z_first - fp_test->geh.zoff ) < IFM_EPSILON )
00845 {
00846
00847
00848
00849 if ( !check_error(&retry, vin->geh.tr, "last slice out of order") )
00850 return 0;
00851
00852 IFM_BIG_ERROR_MESG( "last slice out of order!",
00853 p->fnames[fp->index], z, fp->geh.zoff,
00854 fp->geh.uv17, count + 1, vin->nim );
00855 }
00856 else if ( fabs(vin->z_first - fp->geh.zoff) < IFM_EPSILON )
00857 {
00858
00859
00860
00861 if ( !check_error(&retry, vin->geh.tr, "last slice missing") )
00862 return 0;
00863
00864 missing++;
00865
00866 IFM_BIG_ERROR_MESG( "last slice missing!",
00867 p->fnames[fp->index], z, fp->geh.zoff,
00868 fp->geh.uv17, count + 1, vin->nim );
00869 }
00870 else
00871 {
00872
00873 next_start = find_next_zoff( p, start+count+1, vin->z_first );
00874
00875 if ( next_start < 0 )
00876 return 0;
00877 else
00878 {
00879
00880 if ( !check_error(&retry, vin->geh.tr, "Vol toasted") )
00881 return 0;
00882
00883 IFM_BIG_ERROR_MESG( "Volume severely toasted!",
00884 p->fnames[fp->index], z, fp->geh.zoff,
00885 fp->geh.uv17, count + 1, vin->nim );
00886 }
00887 }
00888 }
00889
00890 if ( next_start < 0)
00891 next_start = start + vin->nim - missing;
00892
00893 if ( retry == 0 && gD.level > 0 )
00894 fprintf(stderr," (retry OK - no errors)\n");
00895
00896 retry = 1;
00897
00898
00899
00900 vout->geh = p->flist[start].geh;
00901 vout->gex = p->flist[start].gex;
00902 vout->nim = next_start - start;
00903 vout->fl_1 = start;
00904 vout->fn_1 = p->flist[start].index;
00905 vout->fn_n = p->flist[start+vout->nim-1].index;
00906 strncpy( vout->first_file, p->fnames[vout->fn_1], IFM_MAX_FLEN );
00907 strncpy( vout->last_file, p->fnames[vout->fn_n], IFM_MAX_FLEN );
00908 vout->z_first = vin->z_first;
00909 vout->z_last = vin->z_last;
00910 vout->z_delta = vin->z_delta;
00911 vout->seq_num = -1;
00912 vout->run = vout->geh.uv17;
00913
00914 if ( vout->nim != vin->nim )
00915 return -1;
00916 else
00917 return 1;
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928 static int check_error( int * retry, float tr, char * note )
00929 {
00930 if ( !retry )
00931 return -1;
00932
00933 if ( *retry == 1 )
00934 {
00935
00936 if ( gD.level > 0 )
00937 fprintf(stderr," (volume retry test for warning '%s'...)\n",
00938 CHECK_NULL_STR(note));
00939
00940 *retry = 0;
00941 sleep( nap_time_from_tr(tr) );
00942 return 0;
00943 }
00944
00945
00946
00947 *retry = 2;
00948
00949 return 1;
00950 }
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 static int read_ge_files(
00967 param_t * p,
00968 int start,
00969 int max )
00970 {
00971 static int org_todo = 1;
00972 int n2scan;
00973 int next = start;
00974
00975 if ( p == NULL )
00976 {
00977 fputs( "failure: RAF: no param_t struct\n", stderr );
00978 return -1;
00979 }
00980
00981
00982 if ( p->fnames && !p->opts.dicom_org )
00983 {
00984 if ( p->nfiles <= 0 )
00985 {
00986 fputs( "failure: RAF: fnames does not match nfiles\n", stderr );
00987 return -1;
00988 }
00989
00990 MCW_free_expand( p->nfiles, p->fnames );
00991 p->fnames = NULL;
00992 }
00993
00994
00995 if ( p->opts.use_dicom )
00996 {
00997 if ( p->opts.dicom_org )
00998 {
00999 if( org_todo )
01000 {
01001 MCW_file_expand(1, &p->glob_dir, &p->nfiles, &p->fnames);
01002 if ( dicom_order_files( p ) != 0 ) return -1;
01003 org_todo = 0;
01004 }
01005 }
01006 else
01007 MCW_file_expand( 1, &p->glob_dir, &p->nfiles, &p->fnames );
01008 }
01009 else
01010 MCW_file_expand( 1, &p->glob_dir, &p->nfiles, &p->fnames );
01011
01012
01013 if ( (next == 0 ) && (p->opts.start_file || p->opts.start_dir) )
01014 {
01015 next = find_fl_file_index( p );
01016
01017 if ( next < 0 )
01018 {
01019 if ( gD.level > 0 )
01020 {
01021 static int attempts = 0;
01022
01023 if ( attempts == 0 )
01024 fprintf(stderr, "-- still searching for start_file, '%s'\n",
01025 p->opts.start_file );
01026
01027 attempts++;
01028 }
01029 return 0;
01030 }
01031 }
01032
01033 if ( gD.level > 4 )
01034 {
01035 int fnum;
01036 for ( fnum = next; fnum < p->nfiles; fnum++ )
01037 printf( "file %4d: %s\n", fnum, p->fnames[fnum] );
01038 }
01039
01040 if ( p->nfiles <= 0 )
01041 return 0;
01042
01043
01044 if ( (max > 0) && (max <= (p->nfiles - next)) )
01045 n2scan = max;
01046 else
01047 n2scan = p->nfiles - next;
01048
01049
01050 if ( (n2scan > p->nalloc) || (max > p->nalloc) )
01051 {
01052 int nalloc;
01053
01054
01055 nalloc = (n2scan >= max) ? n2scan : max;
01056
01057 p->flist = (finfo_t *)realloc( p->flist, nalloc * sizeof(finfo_t) );
01058
01059 if ( p->flist == NULL )
01060 {
01061 fprintf(stderr, "failure to allocate %d finfo_t structs\n", nalloc);
01062 return -1;
01063 }
01064
01065 p->nalloc = nalloc;
01066
01067 if ( gD.level > 1 )
01068 {
01069 idisp_param_t( "++ realloc of flist : ", p );
01070 fprintf( stderr, "-- n2scan = %d, max = %d\n", n2scan, max );
01071 }
01072 }
01073
01074 p->nused = scan_ge_files( p, next, n2scan );
01075
01076 if ( gD.level > 2 )
01077 idisp_param_t( "end read_ge_files : ", p );
01078
01079
01080 return p->nused;
01081 }
01082
01083
01084
01085
01086
01087
01088
01089
01090 static int scan_ge_files (
01091 param_t * p,
01092 int next,
01093 int nfiles )
01094 {
01095 finfo_t * fp;
01096 int im_num, fnum;
01097 int files_read, rv = 0;
01098 int need_M;
01099
01100 if ( nfiles <= 0 )
01101 return 0;
01102
01103 if ( check_im_store_space( &p->im_store, nfiles ) < 0 )
01104 return -1;
01105
01106 p->im_store.nused = 0;
01107
01108 for ( im_num = 0, fnum = next, fp = p->flist;
01109 im_num < nfiles;
01110 im_num++, fnum++, fp++ )
01111 {
01112
01113 if ( im_num < p->im_store.nalloc )
01114 {
01115 fp->image = p->im_store.im_ary[im_num];
01116 need_M = 0;
01117 }
01118 else
01119 {
01120 fp->image = NULL;
01121 need_M = 1;
01122 }
01123
01124 if ( p->opts.use_dicom )
01125 rv = read_dicom_image( p->fnames[fnum], fp, 1 );
01126 else
01127 rv = read_ge_image( p->fnames[fnum], fp, 1, need_M );
01128
01129
01130 if ( (need_M == 1) && (fp->image != NULL) )
01131 {
01132 p->im_store.im_ary[im_num] = fp->image;
01133 p->im_store.nalloc++;
01134
01135
01136 if ( p->im_store.im_size == 0 )
01137 {
01138 if ( alloc_x_im( &p->im_store, fp->bytes ) < 0 )
01139 return -1;
01140 }
01141
01142 if ( gD.level > 1 )
01143 fprintf( stderr, "++ allocated image %d at address %p\n",
01144 im_num, p->im_store.im_ary[im_num] );
01145 }
01146
01147 if ( (rv != 0) || (fp->geh.good != 1) )
01148 {
01149 static int read_failure = -1;
01150 static int fail_count = 0;
01151
01152
01153 if ( read_failure != fnum )
01154 {
01155 read_failure = fnum;
01156 fail_count = 1;
01157 }
01158 else
01159 fail_count++;
01160
01161
01162 if ( fail_count > IFM_MAX_GE_FAILURES )
01163 {
01164 fprintf( stderr, "\n** failure: cannot read image file for "
01165 "file <%s>\n", p->fnames[fnum] );
01166 return -1;
01167 }
01168
01169
01170 if ( gD.level > 1 )
01171 fprintf( stderr, "\n-- (%d) failures to read image file for "
01172 "file <%s>, trying again...\n",
01173 fail_count, p->fnames[fnum] );
01174
01175 break;
01176 }
01177 else
01178 {
01179 p->im_store.nused++;
01180 fp->index = fnum;
01181
01182 if ( gD.level > 2 )
01183 {
01184 idisp_ge_header_info( p->fnames[fp->index], &fp->geh );
01185 idisp_ge_extras( p->fnames[fp->index], &fp->gex );
01186 }
01187 }
01188 }
01189
01190
01191 files_read = fnum - next;
01192
01193 if ( rv == 0 && gD.level > 1 )
01194 printf( "-- scanned %d image files, from <%s> to <%s>\n",
01195 files_read, p->fnames[next], p->fnames[next+files_read-1] );
01196
01197 return files_read;
01198 }
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213 static int dicom_order_files( param_t * p )
01214 {
01215 finfo_t * flist;
01216 char ** new_names;
01217 int rv, bad, c, dcount;
01218 int scount, mcount, smax;
01219
01220 if( p->nfiles <= 0 )
01221 {
01222 fprintf(stderr,"** no DICOM files to order\n");
01223 return 0;
01224 }
01225
01226 if( gD.level > 0 )
01227 fprintf(stderr,"-- checking %d potential DICOM files... 00%%",
01228 p->nfiles);
01229
01230 flist = (finfo_t *)calloc(p->nfiles, sizeof(finfo_t));
01231 if( !flist )
01232 {
01233 fprintf(stderr,"** failed to malloc %d finfo_t structs\n", p->nfiles);
01234 return -1;
01235 }
01236
01237
01238 dcount = 0;
01239 scount = mcount = 0;
01240 smax = (p->nfiles+99)/100;
01241 for( c = 0; c < p->nfiles; c++ )
01242 {
01243 if( read_dicom_image(p->fnames[c], flist+c, 0) != 0 )
01244 {
01245 if( gD.level > 1 )
01246 fprintf(stderr,"** failed to read DICOM file %d of %d, '%s'\n",
01247 c, p->nfiles, p->fnames[c]);
01248 flist[c].geh.uv17 = -1;
01249 }
01250 else
01251 dcount++;
01252 flist[c].index = c;
01253
01254
01255 if( mcount < smax ) mcount++;
01256 else
01257 {
01258 mcount = 0;
01259 scount++;
01260 if(gD.level>0) fprintf(stderr,"%c%c%c%c%c %3d%%",8,8,8,8,8,scount);
01261 }
01262 }
01263 if(gD.level > 0) fprintf(stderr,"%c%c%c%c%c 100%%\n",8,8,8,8,8);
01264 if(gD.level > 0) fprintf(stderr,"++ found %d DICOM files\n", dcount);
01265
01266 if( dcount == 0 )
01267 {
01268 fprintf(stderr,"** found no DICOM files to process\n");
01269 free(flist);
01270 return -1;
01271 }
01272
01273 qsort(flist, p->nfiles, sizeof(finfo_t), compare_finfo);
01274
01275 if( gD.level > 1 && p->nfiles > dcount )
01276 fprintf(stderr,"-d first non-DICOM file is '%s', index %d\n",
01277 p->fnames[flist[dcount].index], flist[dcount].index);
01278
01279
01280 bad = 0;
01281 scount = 0;
01282 for( c = 0; c < dcount-1; c++ )
01283 if( compare_finfo((const void *)(flist+c),
01284 (const void *)(flist+c+1)) >= 0 )
01285 {
01286 bad = 1;
01287 fprintf(stderr,"** flist sort failed for files %s, %s\n"
01288 " (run,index) pairs (%d,%d), (%d,%d)\n",
01289 p->fnames[flist[c].index], p->fnames[flist[c+1].index],
01290 flist[c ].geh.uv17, flist[c ].geh.index,
01291 flist[c+1].geh.uv17, flist[c+1].geh.index);
01292 }
01293 else if( flist[c].index >= flist[c+1].index )
01294 scount++;
01295
01296 if( bad == 1 ){ free(flist); return -1; }
01297
01298
01299 if( scount == 0 && p->nfiles == dcount ) rv = 0;
01300 else rv = 1;
01301
01302 if(gD.level > 0)
01303 {
01304 fprintf(stderr,"-- dicom sort : %d inversions, %d non-DICOM files\n",
01305 scount, p->nfiles-dcount);
01306 if( rv == 0 ) fprintf(stderr," (dicom_org unnecessary)\n");
01307 else fprintf(stderr," (dicom_org was useful)\n");
01308 }
01309
01310
01311 new_names = (char **)malloc(dcount * sizeof(char *));
01312 if( !new_names ) {
01313 fprintf(stderr,"** failed to malloc %d name ptrs\n",dcount);
01314 free(flist);
01315 return -1;
01316 }
01317
01318
01319 for( c = 0; c < dcount; c++ )
01320 new_names[c] = p->fnames[flist[c].index];
01321
01322 for( ; c < p->nfiles; c++ )
01323 {
01324 if( gD.level > 2 )
01325 fprintf(stderr,"-d ignoring non-DICOM file, %s\n",
01326 p->fnames[flist[c].index]);
01327 free(p->fnames[flist[c].index]);
01328 }
01329
01330
01331 free(p->fnames);
01332 p->fnames = new_names;
01333 p->nfiles = dcount;
01334
01335 free(flist);
01336
01337 if(gD.level > 1) fprintf(stderr,"-d dicom_org complete\n");
01338
01339 return 0;
01340 }
01341
01342 int compare_finfo( const void * v0, const void * v1 )
01343 {
01344 ge_header_info * h0 = &((finfo_t *)v0)->geh;
01345 ge_header_info * h1 = &((finfo_t *)v1)->geh;
01346
01347
01348 if ( h1->uv17 < 0 ) return -1;
01349 else if( h0->uv17 < 0 ) return 1;
01350
01351
01352 if( h0->uv17 != h1->uv17 )
01353 {
01354 if( h0->uv17 < h1->uv17 ) return -1;
01355 return 1;
01356 }
01357
01358
01359 if ( h0->index < h1->index ) return -1;
01360 else if( h0->index > h1->index ) return 1;
01361
01362 return 0;
01363 }
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373 static int init_options( param_t * p, ART_comm * A, int argc, char * argv[] )
01374 {
01375 int ac, errors = 0;
01376
01377 if ( p == NULL )
01378 return 2;
01379
01380 if ( argc < 2 )
01381 {
01382 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01383 return 1;
01384 }
01385
01386
01387
01388 memset( p, 0, sizeof(*p) );
01389 memset( &gD, 0, sizeof(gD) );
01390 memset( &gS, 0, sizeof(gS) );
01391 memset( A, 0, sizeof(gAC) );
01392
01393 ART_init_AC_struct( A );
01394 A->param = p;
01395 p->opts.use_dicom = 1;
01396
01397 empty_string_list( &p->opts.drive_list, 0 );
01398 empty_string_list( &p->opts.rt_list, 0 );
01399
01400
01401 gD.level = 1;
01402
01403 for ( ac = 1; ac < argc; ac++ )
01404 {
01405 if ( ! strncmp( argv[ac], "-debug", 4 ) )
01406 {
01407 if ( ++ac >= argc )
01408 {
01409 fputs( "option usage: -debug LEVEL\n", stderr );
01410 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01411 return 1;
01412 }
01413
01414 p->opts.debug = atoi(argv[ac]);
01415 gD.level = p->opts.debug;
01416 if ( gD.level < 0 || gD.level > IFM_MAX_DEBUG )
01417 {
01418 fprintf( stderr, "error: debug level must be in [0,%d]\n",
01419 IFM_MAX_DEBUG );
01420 errors++;
01421 }
01422 }
01423 else if ( ! strncmp( argv[ac], "-dicom_org", 10 ) )
01424 {
01425 p->opts.dicom_org = 1;
01426 }
01427 else if ( ! strncmp( argv[ac], "-GERT_Reco", 7 ) )
01428 {
01429 p->opts.gert_reco = 1;
01430 }
01431 else if ( ! strncmp( argv[ac], "-help", 5 ) )
01432 {
01433 usage( IFM_PROG_NAME, IFM_USE_LONG );
01434 return 1;
01435 }
01436 else if ( ! strncmp( argv[ac], "-hist", 5 ) )
01437 {
01438 usage( IFM_PROG_NAME, IFM_USE_HIST );
01439 return 1;
01440 }
01441 else if ( ! strncmp( argv[ac], "-infile_pattern", 11 ) ||
01442 ! strncmp( argv[ac], "-dicom_glob", 9 ) )
01443 {
01444 if ( ++ac >= argc )
01445 {
01446 fputs( "option usage: -infile_pattern FILE_PATTERN\n", stderr );
01447 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01448 return 1;
01449 }
01450
01451 p->opts.dicom_glob = argv[ac];
01452 }
01453 else if ( ! strncmp( argv[ac], "-infile_prefix", 11 ) )
01454 {
01455 if ( ++ac >= argc )
01456 {
01457 fputs( "option usage: -infile_prefix FILE_PREFIX\n", stderr );
01458 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01459 return 1;
01460 }
01461
01462 p->opts.dicom_glob = calloc(strlen(argv[ac])+2, sizeof(char));
01463 strcpy(p->opts.dicom_glob, argv[ac]);
01464 strcat(p->opts.dicom_glob, "*");
01465 }
01466 else if ( ! strncmp( argv[ac], "-nice", 4 ) )
01467 {
01468 if ( ++ac >= argc )
01469 {
01470 fputs( "option usage: -nice INCREMENT\n", stderr );
01471 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01472 return 1;
01473 }
01474
01475 p->opts.nice = atoi(argv[ac]);
01476 if ( (p->opts.nice < IFM_MIN_NICE_INC) ||
01477 (p->opts.nice > IFM_MAX_NICE_INC) )
01478 {
01479 fprintf( stderr, "error: nice incrment must be in [%d,%d]\n",
01480 IFM_MIN_NICE_INC, IFM_MAX_NICE_INC );
01481 errors++;
01482 }
01483 }
01484 else if ( ! strncmp( argv[ac], "-nt", 3 ) )
01485 {
01486 if ( ++ac >= argc )
01487 {
01488 fputs( "option usage: -nt VOLUMES_PER_RUN\n", stderr );
01489 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01490 return 1;
01491 }
01492
01493 p->opts.nt = atoi(argv[ac]);
01494 if ( p->opts.nt < 0 || p->opts.nt > IFM_MAX_NT )
01495 {
01496 fprintf( stderr,
01497 "option usage: -nt VOLUMES_PER_RUN\n"
01498 " error: VOLUMES_PER_RUN must be in [%d,%d]\n",
01499 0, IFM_MAX_NT );
01500 errors++;
01501 }
01502 }
01503 else if ( ! strncmp( argv[ac], "-od", 3 ) ||
01504 ! strncmp( argv[ac], "-gert_outdir", 9 ) )
01505 {
01506 if ( ++ac >= argc )
01507 {
01508 fputs( "option usage: -gert_outdir OUTPUT_DIR\n", stderr );
01509 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01510 return 1;
01511 }
01512
01513 p->opts.gert_outdir = argv[ac];
01514 }
01515 else if ( ! strncmp( argv[ac], "-pause", 6 ) )
01516 {
01517 if ( ++ac >= argc )
01518 {
01519 fputs( "option usage: -pause milliseconds\n", stderr );
01520 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01521 return 1;
01522 }
01523
01524 p->opts.pause = atoi(argv[ac]);
01525 if ( p->opts.pause < 0 )
01526 {
01527 fprintf(stderr,"** illegal -pause time: %s\n",argv[ac]);
01528 errors++;
01529 }
01530 }
01531 else if ( ! strncmp( argv[ac], "-quiet", 6 ) )
01532 {
01533
01534 if ( gD.level == IFM_DEBUG_DEFAULT )
01535 gD.level = 0;
01536 }
01537 else if ( ! strncmp( argv[ac], "-quit", 5 ) )
01538 {
01539 p->opts.quit = 1;
01540 }
01541 else if ( ! strncmp( argv[ac], "-sp", 3 ) )
01542 {
01543 if ( ++ac >= argc )
01544 {
01545 fputs( "option usage: -sp PATTERN\n", stderr );
01546 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01547 return 1;
01548 }
01549
01550 p->opts.sp = argv[ac];
01551 }
01552 else if ( ! strncmp( argv[ac], "-start_dir", 8 ) )
01553 {
01554 if ( ++ac >= argc )
01555 {
01556 fputs( "option usage: -start_dir DIRECTORY\n", stderr );
01557 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01558 return 1;
01559 }
01560
01561 p->opts.start_dir = argv[ac];
01562 }
01563 else if ( ! strncmp( argv[ac], "-start_file", 8 ) )
01564 {
01565 if ( ++ac >= argc )
01566 {
01567 fputs( "option usage: -start_file DIR/FIRST_FILE\n", stderr );
01568 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01569 return 1;
01570 }
01571
01572 p->opts.start_file = argv[ac];
01573 }
01574 else if ( ! strncmp( argv[ac], "-version", 2 ) )
01575 {
01576 usage( IFM_PROG_NAME, IFM_USE_VERSION );
01577 return 1;
01578 }
01579
01580 else if ( ! strncmp( argv[ac], "-drive_afni", 6 ) )
01581 {
01582 if ( ++ac >= argc )
01583 {
01584 fputs( "option usage: -drive_afni COMMAND\n", stderr );
01585 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01586 return 1;
01587 }
01588
01589 if ( add_to_string_list( &p->opts.drive_list, argv[ac] ) != 0 )
01590 {
01591 fprintf(stderr,"** failed add '%s' to drive_list\n",argv[ac]);
01592 return 1;
01593 }
01594 }
01595 else if ( ! strncmp( argv[ac], "-host", 4 ) )
01596 {
01597 if ( ++ac >= argc )
01598 {
01599 fputs( "option usage: -host HOSTNAME\n", stderr );
01600 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01601 return 1;
01602 }
01603
01604 p->opts.host = argv[ac];
01605 strncpy( A->host, argv[ac], ART_NAME_LEN-1 );
01606 A->host[ART_NAME_LEN-1] = '\0';
01607 }
01608 else if ( ! strncmp( argv[ac], "-rev_byte_order", 4 ) )
01609 {
01610 p->opts.rev_bo = 1;
01611 }
01612 else if ( ! strncmp( argv[ac], "-rt_cmd", 6 ) )
01613 {
01614 if ( ++ac >= argc )
01615 {
01616 fputs( "option usage: -rt_cmd COMMAND\n", stderr );
01617 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01618 return 1;
01619 }
01620
01621 if ( add_to_string_list( &p->opts.rt_list, argv[ac] ) != 0 )
01622 {
01623 fprintf(stderr,"** failed add '%s' to rt_list\n",argv[ac]);
01624 return 1;
01625 }
01626 }
01627 else if ( ! strncmp( argv[ac], "-rt", 3 ) )
01628 {
01629 A->state = ART_STATE_TO_OPEN;
01630 p->opts.rt = 1;
01631 }
01632 else if ( ! strncmp( argv[ac], "-swap", 5 ) )
01633 {
01634 A->swap = 1;
01635 p->opts.swap = 1;
01636 }
01637 else if ( ! strncmp( argv[ac], "-use_imon", 7 ) )
01638 {
01639
01640 p->opts.use_dicom = 0;
01641 }
01642 else if ( ! strncmp( argv[ac], "-zorder", 6 ) )
01643 {
01644 if ( ++ac >= argc )
01645 {
01646 fputs( "option usage: -zorder ORDER\n", stderr );
01647 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01648 return 1;
01649 }
01650
01651 A->zorder = argv[ac];
01652 }
01653 else
01654 {
01655 fprintf( stderr, "error: invalid option <%s>\n\n", argv[ac] );
01656 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01657 return 1;
01658 }
01659 }
01660
01661 if ( errors > 0 )
01662 {
01663 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01664 return 1;
01665 }
01666
01667 if ( p->opts.start_dir == NULL && !p->opts.use_dicom )
01668 {
01669 fputs( "error: missing '-start_dir DIR' option\n", stderr );
01670 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01671 return 1;
01672 }
01673
01674 if ( p->opts.rev_bo && p->opts.swap )
01675 {
01676 fprintf( stderr, "error: options '-rev_byte_order' and '-swap' "
01677 "cannot both be used\n");
01678 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01679 return 1;
01680 }
01681
01682 if ( A->zorder )
01683 {
01684 if ( strcmp(A->zorder, "alt") && strcmp(A->zorder, "seq") )
01685 {
01686 fprintf(stderr,"** order '%s' is invalid for '-zorder' option,\n"
01687 " must be either 'alt' or 'seq'\n", A->zorder);
01688 return 1;
01689 }
01690 }
01691
01692 if ( p->opts.use_dicom )
01693 {
01694 if( ! p->opts.dicom_glob )
01695 {
01696 fprintf(stderr,"** missing -infile_pattern option\n");
01697 return 1;
01698 }
01699 }
01700
01701
01702
01703
01704 if ( p->opts.use_dicom )
01705 {
01706 p->glob_dir = p->opts.dicom_glob;
01707 p->ftype = IFM_IM_FTYPE_DICOM;
01708 }
01709 else
01710 {
01711 if ( dir_expansion_form(p->opts.start_dir, &p->glob_dir) ) return 2;
01712 p->ftype = IFM_IM_FTYPE_GEMS5;
01713 }
01714
01715
01716 p->opts.argv = argv;
01717 p->opts.argc = argc;
01718
01719 if ( gD.level > 1 )
01720 {
01721 idisp_opts_t ( "end init_options : ", &p->opts );
01722 idisp_param_t( "end init_options : ", p );
01723 }
01724
01725
01726 if ( p->opts.use_dicom )
01727 rglob_set_sort_dir( 1 );
01728
01729 if ( gD.level > 0 )
01730 fprintf( stderr, "\n%s running, use <ctrl-c> to quit...\n\n",
01731 IFM_PROG_NAME );
01732
01733 return 0;
01734 }
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745 static int init_extras( param_t * p, ART_comm * ac )
01746 {
01747 if ( p->opts.nice && set_nice_level(p->opts.nice) )
01748 return 1;
01749
01750 if ( ac->state == ART_STATE_TO_OPEN )
01751 {
01752 atexit( ART_exit );
01753 ac->mode = AFNI_OPEN_CONTROL_MODE;
01754 ART_open_afni_link( ac, 2, 1, gD.level );
01755 }
01756
01757
01758 if ( p->opts.start_file != NULL )
01759 {
01760 char * sf = p->opts.start_file;
01761 char * gd = p->glob_dir;
01762 int flevel = str_char_count( sf, strlen(sf), (char)'/' );
01763
01764
01765 if ( flevel != str_char_count( gd, strlen(gd), (char)'/' ) )
01766 {
01767 fprintf( stderr,
01768 "** warning : relative path to : '-start_dir %s'\n"
01769 " does not seem to match : '-start_file %s'\n"
01770 " (so 'start_file' may never be found)\n\n",
01771 p->opts.start_file, p->opts.start_dir );
01772 }
01773 else if ( gD.level > 1 )
01774 fprintf( stderr, "-- '-start_file %s' and\n"
01775 " '-start_dir %s' match at dir level %d\n",
01776 p->opts.start_file, p->opts.start_dir, flevel );
01777 }
01778
01779 return 0;
01780 }
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790 static int set_nice_level( int level )
01791 {
01792 int rv;
01793
01794 rv = nice( level );
01795 if ( rv != 0 )
01796 {
01797 if ( level < 0 )
01798 fprintf( stderr, "error: only root may decrement nice value\n"
01799 " (errno = %d, rv = %d)\n", errno, rv );
01800 else
01801 fprintf( stderr,
01802 "error: failure to adjust nice by %d\n"
01803 " (errno = %d, rv = %d)\n", level, errno, rv );
01804 }
01805 else if ( gD.level > 1 )
01806 fprintf( stderr, "-- nice value incremented by %d\n", level );
01807
01808 return rv;
01809 }
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824 int dir_expansion_form( char * sin, char ** sexp )
01825 {
01826 char * out;
01827 char * cp;
01828 char d0, d1, d2;
01829 int len;
01830
01831 if ( (sin == NULL) || (sexp == NULL) )
01832 return -1;
01833
01834 *sexp = NULL;
01835 len = strlen(sin);
01836
01837 out = (char *)malloc((len + IFM_PAD_LEN) * sizeof(char));
01838 if ( out == NULL )
01839 {
01840 fprintf( stderr, "failure: dir_expansion_form malloc\n" );
01841 return -1;
01842 }
01843
01844 *sexp = out;
01845
01846 strcpy( out,sin );
01847
01848 cp = out + len - 1;
01849
01850
01851 while ( (cp > (out+2)) && !isdigit( *cp ) )
01852 cp--;
01853
01854 if ( !isdigit(*cp) )
01855 {
01856 fprintf( stderr, "error: dir <%s> is not of the form 00n (e.g. 003)\n",
01857 sin );
01858 free(out);
01859 return -1;
01860 }
01861
01862 cp -= 2;
01863
01864 d0 = cp[0];
01865 d1 = cp[1];
01866 d2 = cp[2];
01867
01868 if ( (d0 != '0') ||
01869 ( (d1 != '0') && (d1 != '1')) )
01870 {
01871 fprintf( stderr, "error: dir <%s> is not of the form 0[01]n"
01872 " (e.g. 003)\n", sin );
01873 free(out);
01874 return -1;
01875 }
01876
01877
01878
01879
01880 strcpy( cp, "[0-9]" );
01881 cp += strlen( "[0-9]" );
01882
01883 if ( d1 == '0' )
01884 strcpy( cp, "[02468]" );
01885 else
01886 strcpy( cp, "[13579]" );
01887 cp += strlen( "[02468]" );
01888
01889 *cp++ = d2;
01890
01891
01892 strcpy( cp, "/[Ii].*" );
01893
01894 return 0;
01895 }
01896
01897
01898
01899
01900
01901 static int read_dicom_image( char * pathname, finfo_t * fp, int get_data )
01902 {
01903 MRI_IMAGE * im;
01904
01905 im = r_mri_read_dicom( pathname, gD.level, get_data ? &fp->image : NULL);
01906 if ( !im )
01907 {
01908 fprintf(stderr,"** failed to read file '%s' as dicom\n", pathname);
01909 return 1;
01910 }
01911
01912 if ( gD.level > 2 )
01913 {
01914 fprintf(stderr,"+d dinfo (%s): std, ser, im = (%d, %d, %3d)\n",
01915 pathname,
01916 gr_dimon_stuff.study, gr_dimon_stuff.series, gr_dimon_stuff.image );
01917 fprintf(stderr," im->xo,yo,zo = (%6.1f,%6.1f,%6.1f)\n",
01918 im->xo, im->yo, im->zo);
01919 }
01920
01921
01922
01923 fp->geh.good = 1;
01924 fp->geh.nx = im->nx;
01925 fp->geh.ny = im->ny;
01926 fp->geh.uv17 = gr_dimon_stuff.series;
01927 fp->geh.index = gr_dimon_stuff.image;
01928 fp->geh.dx = im->dx;
01929 fp->geh.dy = im->dy;
01930 fp->geh.dz = im->dz;
01931 fp->geh.zoff = im->zo;
01932
01933
01934 fp->geh.tr = DI_MRL_tr;
01935 fp->geh.te = 0;
01936 memset(fp->geh.orients, 0, 8);
01937 strncpy(fp->geh.orients, DI_MRL_orients, 7);
01938
01939
01940 fp->gex.bpp = im->pixel_size;
01941 fp->gex.cflag = 0;
01942 fp->gex.hdroff = -1;
01943 fp->gex.skip = -1;
01944 fp->gex.swap = im->was_swapped;
01945 fp->gex.kk = 0;
01946 fp->gex.xorg = im->xo;
01947 fp->gex.yorg = im->yo;
01948
01949
01950
01951 fp->bytes = im->nvox * im->pixel_size;
01952
01953 free(im);
01954
01955 return 0;
01956 }
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966 static int read_ge_image( char * pathname, finfo_t * fp,
01967 int get_image, int need_memory )
01968 {
01969 ge_header_info * hi = &fp->geh;
01970
01971 FILE *imfile ;
01972 int length , skip , swap=0 ;
01973 char orients[8] , str[8] ;
01974 int nx , ny , bpp , cflag , hdroff ;
01975 float uv17 = -1.0;
01976
01977 if( hi == NULL ) return -1;
01978 hi->good = 0 ;
01979 if( pathname == NULL ||
01980 pathname[0] == '\0' ) return -1;
01981
01982 length = l_THD_filesize( pathname ) ;
01983 if( length < 1024 ) return -1;
01984
01985 imfile = fopen( pathname , "r" ) ;
01986 if( imfile == NULL ) return -1;
01987
01988 strcpy(str,"JUNK") ;
01989 fread(str,1,4,imfile) ;
01990
01991 if( str[0]!='I' || str[1]!='M' || str[2]!='G' || str[3]!='F' ){
01992 fclose(imfile) ; return -2;
01993 }
01994
01995
01996
01997 fread( &skip , 4,1, imfile ) ;
01998 fread( &nx , 4,1, imfile ) ;
01999 fread( &ny , 4,1, imfile ) ;
02000 fread( &bpp , 4,1, imfile ) ;
02001 fread( &cflag, 4,1, imfile ) ;
02002
02003
02004
02005 if( nx < 0 || nx > 8192 ){
02006 swap = 1 ;
02007 swap_4(&skip); swap_4(&nx); swap_4(&ny); swap_4(&bpp); swap_4(&cflag);
02008 } else {
02009 swap = 0 ;
02010 }
02011 if( nx < 0 || nx > 8192 || ny < 0 || ny > 8192 ){
02012 fclose(imfile) ; return -1;
02013 }
02014
02015 hi->nx = nx ;
02016 hi->ny = ny ;
02017
02018 if( skip+2*nx*ny > length ||
02019 skip <= 0 ||
02020 cflag != 1 ||
02021 bpp != 16 ){
02022 fclose(imfile); return -1;
02023 }
02024
02025
02026
02027 fseek( imfile , 148L , SEEK_SET ) ;
02028 fread( &hdroff , 4,1 , imfile ) ;
02029 if( swap ) swap_4(&hdroff) ;
02030
02031 if( hdroff > 0 && hdroff+256 < length ){
02032 float dx,dy,dz, xyz[9], zz ; int itr, ii,jj,kk ;
02033
02034
02035
02036 fseek( imfile , hdroff+26 , SEEK_SET ) ;
02037 fread( &dz , 4,1 , imfile ) ;
02038
02039 fseek( imfile , hdroff+50 , SEEK_SET ) ;
02040 fread( &dx , 4,1 , imfile ) ;
02041 fread( &dy , 4,1 , imfile ) ;
02042
02043 if( swap ){ swap_4(&dx); swap_4(&dy); swap_4(&dz); }
02044
02045 hi->dx = dx ; hi->dy = dy ; hi->dz = dz ;
02046
02047
02048
02049
02050
02051
02052
02053 fseek( imfile , hdroff+154 , SEEK_SET ) ;
02054 fread( xyz , 4,9 , imfile ) ;
02055 if( swap ){
02056 swap_4(xyz+0); swap_4(xyz+1); swap_4(xyz+2);
02057 swap_4(xyz+3); swap_4(xyz+4); swap_4(xyz+5);
02058 swap_4(xyz+6); swap_4(xyz+7); swap_4(xyz+8);
02059 }
02060
02061
02062
02063
02064
02065
02066 dx = fabs(xyz[3]-xyz[0]) ; ii = 1 ;
02067 dy = fabs(xyz[4]-xyz[1]) ; if( dy > dx ){ ii=2; dx=dy; }
02068 dz = fabs(xyz[5]-xyz[2]) ; if( dz > dx ){ ii=3; }
02069 dx = xyz[ii+2]-xyz[ii-1] ; if( dx < 0. ){ ii = -ii; }
02070 switch( ii ){
02071 case 1: orients[0]= 'L'; orients[1]= 'R'; break;
02072 case -1: orients[0]= 'R'; orients[1]= 'L'; break;
02073 case 2: orients[0]= 'P'; orients[1]= 'A'; break;
02074 case -2: orients[0]= 'A'; orients[1]= 'P'; break;
02075 case 3: orients[0]= 'I'; orients[1]= 'S'; break;
02076 case -3: orients[0]= 'S'; orients[1]= 'I'; break;
02077 default: orients[0]='\0'; orients[1]='\0'; break;
02078 }
02079
02080
02081
02082
02083
02084
02085 dx = fabs(xyz[6]-xyz[3]) ; jj = 1 ;
02086 dy = fabs(xyz[7]-xyz[4]) ; if( dy > dx ){ jj=2; dx=dy; }
02087 dz = fabs(xyz[8]-xyz[5]) ; if( dz > dx ){ jj=3; }
02088 dx = xyz[jj+5]-xyz[jj+2] ; if( dx < 0. ){ jj = -jj; }
02089 switch( jj ){
02090 case 1: orients[2] = 'L'; orients[3] = 'R'; break;
02091 case -1: orients[2] = 'R'; orients[3] = 'L'; break;
02092 case 2: orients[2] = 'P'; orients[3] = 'A'; break;
02093 case -2: orients[2] = 'A'; orients[3] = 'P'; break;
02094 case 3: orients[2] = 'I'; orients[3] = 'S'; break;
02095 case -3: orients[2] = 'S'; orients[3] = 'I'; break;
02096 default: orients[2] ='\0'; orients[3] ='\0'; break;
02097 }
02098
02099 orients[4] = '\0' ;
02100
02101 kk = 6 - abs(ii)-abs(jj) ;
02102
02103
02104
02105 zz = xyz[kk-1] ;
02106
02107 hi->zoff = zz ;
02108 strcpy(hi->orients,orients) ;
02109
02110
02111
02112 fp->gex.xorg = xyz[abs(ii)-1];
02113 fp->gex.yorg = xyz[abs(jj)-1];
02114
02115
02116
02117 fseek( imfile , hdroff+194 , SEEK_SET ) ;
02118 fread( &itr , 4,1 , imfile ) ;
02119 if( swap ) swap_4(&itr) ;
02120 hi->tr = 1.0e-6 * itr ;
02121
02122
02123
02124 fseek( imfile , hdroff+202 , SEEK_SET ) ;
02125 fread( &itr , 4,1 , imfile ) ;
02126 if( swap ) swap_4(&itr) ;
02127 hi->te = 1.0e-6 * itr ;
02128
02129
02130
02131
02132
02133
02134
02135 fseek ( imfile , hdroff+272+202, SEEK_SET ) ;
02136 fread( &uv17 , 4, 1 , imfile ) ;
02137 if( swap ) swap_4(&uv17) ;
02138
02139 hi->uv17 = (int)uv17;
02140
02141
02142
02143 fp->gex.bpp = bpp;
02144 fp->gex.cflag = cflag;
02145 fp->gex.hdroff = hdroff;
02146 fp->gex.skip = skip;
02147 fp->gex.swap = swap;
02148 fp->gex.kk = kk;
02149
02150 memcpy( fp->gex.xyz, xyz, sizeof(xyz) );
02151
02152 hi->good = 1 ;
02153
02154 }
02155
02156
02157 if ( get_image )
02158 {
02159 int elements = hi->nx * hi->ny;
02160
02161 fp->bytes = elements * 2;
02162
02163 if ( need_memory )
02164 fp->image = malloc( fp->bytes );
02165
02166 if ( fp->image == NULL )
02167 {
02168 fprintf(stderr, "** RGI: no memory for %d byte image\n", fp->bytes);
02169 hi->good = 0;
02170 return -1;
02171 }
02172
02173 fseek ( imfile, skip, SEEK_SET );
02174 if ( fread( fp->image , 2, elements, imfile ) != elements )
02175 {
02176 fprintf( stderr, "** RGI: failed to read %d shorts from %s\n",
02177 elements, pathname );
02178 hi->good = 0;
02179 return -1;
02180 }
02181 }
02182
02183 fclose(imfile);
02184 return 0;
02185 }
02186
02187
02188
02189
02190
02191
02192 static int swap_4( void * ptr )
02193 {
02194 unsigned char * addr = ptr;
02195
02196 addr[0] ^= addr[3]; addr[3] ^= addr[0]; addr[0] ^= addr[3];
02197 addr[1] ^= addr[2]; addr[2] ^= addr[1]; addr[1] ^= addr[2];
02198
02199 return 0;
02200 }
02201
02202
02203
02204
02205
02206
02207 static int idisp_im_store_t( char * info, im_store_t * is )
02208 {
02209 if ( info )
02210 fputs( info, stdout );
02211
02212 if ( is == NULL )
02213 {
02214 printf( "idisp_im_store_t: is == NULL\n" );
02215 return -1;
02216 }
02217
02218 printf( "im_store_t struct at %p :\n"
02219 " (nalloc, nused) = (%d, %d)\n"
02220 " (ary_len, im_size) = (%d, %d)\n"
02221 " (im_ary, x_im) = (%p, %p)\n",
02222 is, is->nalloc, is->nused,
02223 is->ary_len, is->im_size, is->im_ary, is->x_im );
02224
02225 return 0;
02226 }
02227
02228
02229
02230
02231
02232
02233 static int idisp_param_t( char * info, param_t * p )
02234 {
02235 if ( info )
02236 fputs( info, stdout );
02237
02238 if ( p == NULL )
02239 {
02240 printf( "idisp_param_t: p == NULL\n" );
02241 return -1;
02242 }
02243
02244 printf( "param_t struct at %p :\n"
02245 " ftype = %d\n"
02246 " (nused, nalloc) = (%d, %d)\n"
02247 " flist = %p\n"
02248 " glob_dir = %s\n"
02249 " nfiles = %d\n"
02250 " fnames = %p\n",
02251 p, p->ftype, p->nused, p->nalloc, p->flist,
02252 CHECK_NULL_STR(p->glob_dir),
02253 p->nfiles, p->fnames );
02254
02255 return 0;
02256 }
02257
02258
02259
02260
02261
02262
02263 static int idisp_opts_t( char * info, opts_t * opt )
02264 {
02265 if ( info )
02266 fputs( info, stdout );
02267
02268 if ( opt == NULL )
02269 {
02270 printf( "idisp_opts_t: opt == NULL\n" );
02271 return -1;
02272 }
02273
02274 printf( "opts_t struct at %p :\n"
02275 " start_file = %s\n"
02276 " start_dir = %s\n"
02277 " dicom_glob = %s\n"
02278 " sp = %s\n"
02279 " gert_outdir = %s\n"
02280 " (argv, argc) = (%p, %d)\n"
02281 " (nt, nice) = (%d, %d)\n"
02282 " pause = %d\n"
02283 " (debug, gert_reco) = (%d, %d)\n"
02284 " use_dicom, quit = %d, %d\n"
02285 " (rt, swap, rev_bo) = (%d, %d, %d)\n"
02286 " host = %s\n"
02287 " drive_list(u,a,p) = %d, %d, %p\n"
02288 " rt_list (u,a,p) = %d, %d, %p\n",
02289 opt,
02290 CHECK_NULL_STR(opt->start_file),
02291 CHECK_NULL_STR(opt->start_dir),
02292 CHECK_NULL_STR(opt->dicom_glob),
02293 CHECK_NULL_STR(opt->sp),
02294 CHECK_NULL_STR(opt->gert_outdir),
02295 opt->argv, opt->argc,
02296 opt->nt, opt->nice, opt->pause,
02297 opt->debug, opt->gert_reco, opt->use_dicom, opt->quit,
02298 opt->rt, opt->swap, opt->rev_bo,
02299 CHECK_NULL_STR(opt->host),
02300 opt->drive_list.nused, opt->drive_list.nalloc, opt->drive_list.str,
02301 opt->rt_list.nused, opt->rt_list.nalloc, opt->rt_list.str
02302 );
02303
02304 return 0;
02305 }
02306
02307
02308
02309
02310
02311
02312 static int disp_ftype( char * info, int ftype )
02313 {
02314 if ( info ) fputs(info, stdout);
02315
02316 switch( ftype )
02317 {
02318 case IFM_IM_FTYPE_GEMS5:
02319 printf("GEMS 5.x\n");
02320 break;
02321
02322 case IFM_IM_FTYPE_DICOM:
02323 printf("DICOM\n");
02324 break;
02325
02326 default:
02327 printf("UNKNOWN (%d)\n", ftype);
02328 break;
02329 }
02330
02331 fflush(stdout);
02332
02333 return 0;
02334 }
02335
02336
02337
02338
02339
02340 static int idisp_vol_t( char * info, vol_t * v )
02341 {
02342 if ( info )
02343 fputs( info, stdout );
02344
02345 if ( v == NULL )
02346 {
02347 printf( "idisp_vol_t: v == NULL\n" );
02348 return -1;
02349 }
02350
02351 printf( "vol_t struct at %p :\n"
02352 " nim = %d\n"
02353 " (fl_1, fn_1, fn_n) = (%d, %d, %d)\n"
02354 " first_file = %s\n"
02355 " last_file = %s\n"
02356 " (z_first, z_last) = (%f, %f)\n"
02357 " z_delta = %f\n"
02358 " (seq_num, run) = (%d, %d)\n",
02359 v, v->nim, v->fl_1, v->fn_1, v->fn_n,
02360 v->first_file, v->last_file,
02361 v->z_first, v->z_last, v->z_delta,
02362 v->seq_num, v->run );
02363
02364 idisp_ge_header_info( info, &v->geh );
02365 idisp_ge_extras( info, &v->gex );
02366
02367 return 0;
02368 }
02369
02370
02371
02372
02373
02374
02375
02376 static int idisp_ge_extras( char * info, ge_extras * E )
02377 {
02378 if ( info )
02379 fputs( info, stdout );
02380
02381 if ( E == NULL )
02382 {
02383 printf( "idisp_ge_extras: E == NULL\n" );
02384 return -1;
02385 }
02386
02387 printf( "ge_extras at %p :\n"
02388 " bpp = %d\n"
02389 " cflag = %d\n"
02390 " hdroff = %d\n"
02391 " skip = %d\n"
02392 " swap = %d\n"
02393 " kk = %d\n"
02394 " xorg = %f\n"
02395 " yorg = %f\n"
02396 " (xyz0,xyz1,xyz2) = (%f,%f,%f)\n"
02397 " (xyz3,xyz4,xyz5) = (%f,%f,%f)\n"
02398 " (xyz6,xyz7,xyz8) = (%f,%f,%f)\n",
02399 E, E->bpp, E->cflag, E->hdroff, E->skip, E->swap, E->kk,
02400 E->xorg, E->yorg,
02401 E->xyz[0], E->xyz[1], E->xyz[2],
02402 E->xyz[3], E->xyz[4], E->xyz[5],
02403 E->xyz[6], E->xyz[7], E->xyz[8]
02404 );
02405 return 0;
02406 }
02407
02408
02409
02410
02411
02412
02413 static int idisp_ge_header_info( char * info, ge_header_info * I )
02414 {
02415 if ( info )
02416 fputs( info, stdout );
02417
02418 if ( I == NULL )
02419 {
02420 printf( "idisp_ge_header_info: I == NULL\n" );
02421 return -1;
02422 }
02423
02424 printf( "ge_header_info at %p :\n"
02425 " good = %d\n"
02426 " (nx,ny) = (%d,%d)\n"
02427 " uv17 = %d\n"
02428 " index = %d\n"
02429 " (dx,dy,dz) = (%f,%f,%f)\n"
02430 " zoff = %f\n"
02431 " (tr,te) = (%f,%f)\n"
02432 " orients = %-8s\n",
02433 I, I->good, I->nx, I->ny, I->uv17, I->index,
02434 I->dx, I->dy, I->dz, I->zoff, I->tr, I->te,
02435 CHECK_NULL_STR(I->orients)
02436 );
02437
02438 return 0;
02439 }
02440
02441
02442
02443
02444
02445 static int usage ( char * prog, int level )
02446 {
02447 if ( level == IFM_USE_SHORT )
02448 {
02449 fprintf( stderr,
02450 "usage: %s [options] -start_dir DIR\n"
02451 "usage: %s -help\n",
02452 prog, prog );
02453 return 0;
02454 }
02455 else if ( level == IFM_USE_LONG )
02456 {
02457 printf(
02458 "\n"
02459 "%s - monitor real-time acquisition of DICOM image files\n"
02460 " (or GEMS 5.x I-files, as 'Imon')\n"
02461 "\n"
02462 " This program is intended to be run during a scanning session\n"
02463 " on a scanner, to monitor the collection of image files. The\n"
02464 " user will be notified of any missing slice or any slice that\n"
02465 " is aquired out of order.\n"
02466 "\n"
02467 " When collecting DICOM files, it is recommended to run this\n"
02468 " once per run, only because it is easier to specify the input\n"
02469 " file pattern for a single run (it may be very difficult to\n"
02470 " predict the form of input filenames runs that have not yet\n"
02471 " occurred.\n"
02472 "\n"
02473 " This program can also be used off-line (away from the scanner)\n"
02474 " to organize the files, run by run. If the DICOM files have\n"
02475 " a correct DICOM 'image number' (0x0020 0013), then Dimon can\n"
02476 " use the information to organize the sequence of the files, \n"
02477 " particularly when the alphabetization of the filenames does\n"
02478 " not match the sequencing of the slice positions. This can be\n"
02479 " used in conjunction with the '-GERT_Reco' option, which will\n"
02480 " write a script that can be used to create AFNI datasets.\n"
02481 "\n"
02482 " See the '-dicom_org' option, under 'other options', below.\n"
02483 "\n"
02484 " If no -quit option is provided, the user should terminate the\n"
02485 " program when it is done collecting images according to the\n"
02486 " input file pattern.\n"
02487 "\n"
02488 " Dimon can be terminated using <ctrl-c>.\n"
02489 "\n"
02490 " ---------------------------------------------------------------\n"
02491 " realtime notes for running afni remotely:\n"
02492 "\n"
02493 " - The afni program must be started with the '-rt' option to\n"
02494 " invoke the realtime plugin functionality.\n"
02495 "\n"
02496 " - If afni is run remotely, then AFNI_TRUSTHOST will need to be\n"
02497 " set on the host running afni. The value of that variable\n"
02498 " should be set to the IP address of the host running %s.\n"
02499 " This may set as an environment variable, or via the .afnirc\n"
02500 " startup file.\n"
02501 "\n"
02502 " - The typical default security on a Linux system will prevent\n"
02503 " %s from communicating with afni on the host running afni.\n"
02504 " The iptables firewall service on afni's host will need to be\n"
02505 " configured to accept the communication from the host running\n"
02506 " %s, or it (iptables) will need to be turned off.\n"
02507 " ---------------------------------------------------------------\n"
02508 " usage: %s [options] -infile_prefix PREFIX\n"
02509 " OR: %s [options] -infile_pattern \"PATTERN\"\n"
02510 "\n"
02511 " ---------------------------------------------------------------\n"
02512 " examples (no real-time options):\n"
02513 "\n"
02514 " %s -infile_pattern 's8912345/i*'\n"
02515 " %s -infile_prefix s8912345/i\n"
02516 " %s -help\n"
02517 " %s -infile_prefix s8912345/i -quit\n"
02518 " %s -infile_prefix s8912345/i -nt 120 -quit\n"
02519 " %s -infile_prefix s8912345/i -debug 2\n"
02520 " %s -infile_prefix s8912345/i -dicom_org -GERT_Reco -quit\n"
02521 "\n"
02522 " examples (with real-time options):\n"
02523 "\n"
02524 " %s -infile_prefix s8912345/i -rt \n"
02525 "\n"
02526 " %s -infile_pattern 's*/i*' -rt \n"
02527 " %s -infile_pattern 's*/i*' -rt -nt 120\n"
02528 " %s -infile_pattern 's*/i*' -rt -quit\n"
02529 "\n"
02530 " ** detailed real-time example:\n"
02531 " %s \\\n"
02532 " -infile_pattern 's*/i*' \\\n"
02533 " -rt -nt 120 \\\n"
02534 " -host some.remote.computer \\\n"
02535 " -rt_cmd \"PREFIX 2005_0513_run3\" \\\n"
02536 " -quit \n"
02537 "\n"
02538 " This example scans data starting from directory 003, expects\n"
02539 " 160 repetitions (TRs), and invokes the real-time processing,\n"
02540 " sending data to a computer called some.remote.computer.name\n"
02541 " (where afni is running, and which considers THIS computer to\n"
02542 " be trusted - see the AFNI_TRUSTHOST environment variable).\n"
02543 "\n"
02544 " ---------------------------------------------------------------\n"
02545 " Multiple DRIVE_AFNI commands are passed through '-drive_afni'\n"
02546 " options, one requesting to open an axial image window, and\n"
02547 " another requesting an axial graph, with 160 data points.\n"
02548 "\n"
02549 " See README.driver for acceptable DRIVE_AFNI commands.\n"
02550 "\n"
02551 " Also, multiple commands specific to the real-time plugin are\n"
02552 " passed via '-rt_cmd' options. The PREFIX command sets the\n"
02553 " prefix for the datasets output by afni. The GRAPH_XRANGE and\n"
02554 " GRAPH_YRANGE commands set the graph dimensions for the 3D\n"
02555 " motion correction graph (only). And the GRAPH_EXPR command\n"
02556 " is used to replace the 6 default motion correction graphs with\n"
02557 " a single graph, according to the given expression, the square\n"
02558 " root of the average squared entry of the 3 rotaion parameters,\n"
02559 " roll, pitch and yaw, ignoring the 3 shift parameters, dx, dy\n"
02560 " and dz.\n"
02561 "\n"
02562 " See README.realtime for acceptable DRIVE_AFNI commands.\n"
02563 "\n"
02564 " %s \\\n"
02565 " -infile_pattern 's*/i*.dcm' \\\n"
02566 " -nt 160 \\\n"
02567 " -rt \\\n"
02568 " -host some.remote.computer.name \\\n"
02569 " -drive_afni 'OPEN_WINDOW axialimage' \\\n"
02570 " -drive_afni 'OPEN_WINDOW axialgraph pinnum=160' \\\n"
02571 " -rt_cmd 'PREFIX eat.more.cheese' \\\n"
02572 " -rt_cmd 'GRAPH_XRANGE 160' \\\n"
02573 " -rt_cmd 'GRAPH_YRANGE 1.02' \\\n"
02574 " -rt_cmd 'GRAPH_EXPR sqrt((d*d+e*e+f*f)/3)' \n"
02575 "\n"
02576 " ---------------------------------------------------------------\n",
02577 prog, prog, prog, prog, prog, prog,
02578 prog, prog, prog, prog, prog, prog,
02579 prog, prog, prog, prog, prog, prog, prog );
02580
02581 printf(
02582 " notes:\n"
02583 "\n"
02584 " - Once started, unless the '-quit' option is used, this\n"
02585 " program exits only when a fatal error occurs (single\n"
02586 " missing or out of order slices are not considered fatal).\n"
02587 " Otherwise, it keeps waiting for new data to arrive.\n"
02588 "\n"
02589 " With the '-quit' option, the program will terminate once\n"
02590 " there is a significant (~2 TR) pause in acquisition.\n"
02591 "\n"
02592 " - To terminate this program, use <ctrl-c>.\n"
02593 "\n"
02594 " ---------------------------------------------------------------\n"
02595 " main options:\n"
02596 "\n"
02597 " For DICOM images, either -infile_pattern or -infile_prefix\n"
02598 " is required.\n"
02599 "\n"
02600 " -infile_pattern PATTERN : specify pattern for input files\n"
02601 "\n"
02602 " e.g. -infile_pattern 'run1/i*.dcm'\n"
02603 "\n"
02604 " This option is used to specify a wildcard pattern matching\n"
02605 " the names of the input DICOM files. These files should be\n"
02606 " sorted in the order that they are to be assembled, i.e.\n"
02607 " when the files are sorted alphabetically, they should be\n"
02608 " sequential slices in a volume, and the volumes should then\n"
02609 " progress over time (as with the 'to3d' program).\n"
02610 "\n"
02611 " The pattern for this option must be within quotes, because\n"
02612 " it will be up to the program to search for new files (that\n"
02613 " match the pattern), not the shell.\n"
02614 "\n"
02615 " -infile_prefix PREFIX : specify prefix matching input files\n"
02616 "\n"
02617 " e.g. -infile_prefix run1/i\n"
02618 "\n"
02619 " This option is similar to -infile_pattern. By providing\n"
02620 " only a prefix, the user need not use wildcard characters\n"
02621 " with quotes. Using PREFIX with -infile_prefix is\n"
02622 " equivalent to using 'PREFIX*' with -infile_pattern (note\n"
02623 " the needed quotes).\n"
02624 "\n"
02625 " Note that it may not be a good idea to use, say 'run1/'\n"
02626 " for the prefix, as there might be a readme file under\n"
02627 " that directory.\n"
02628 "\n"
02629 " Note also that it is necessary to provide a '/' at the\n"
02630 " end, if the prefix is a directory (e.g. use run1/ instead\n"
02631 " of simply run1).\n"
02632 "\n"
02633 " ---------------------------------------------------------------\n"
02634 " real-time options:\n"
02635 "\n"
02636 " -rt : specify to use the real-time facility\n"
02637 "\n"
02638 " With this option, the user tells '%s' to use the real-time\n"
02639 " facility, passing each volume of images to an existing\n"
02640 " afni process on some machine (as specified by the '-host'\n"
02641 " option). Whenever a new volume is aquired, it will be\n"
02642 " sent to the afni program for immediate update.\n"
02643 "\n"
02644 " Note that afni must also be started with the '-rt' option\n"
02645 " to make use of this.\n"
02646 "\n"
02647 " Note also that the '-host HOSTNAME' option is not required\n"
02648 " if afni is running on the same machine.\n"
02649 "\n"
02650 " -drive_afni CMND : send 'drive afni' command, CMND\n"
02651 "\n"
02652 " e.g. -drive_afni 'OPEN_WINDOW axialimage'\n"
02653 "\n"
02654 " This option is used to pass a single DRIVE_AFNI command\n"
02655 " to afni. For example, 'OPEN_WINDOW axialimage' will open\n"
02656 " such an axial view window on the afni controller.\n"
02657 "\n"
02658 " Note: the command 'CMND' must be given in quotes, so that\n"
02659 " the shell will send it as a single parameter.\n"
02660 "\n"
02661 " Note: this option may be used multiple times.\n"
02662 "\n"
02663 " See README.driver for more details.\n"
02664 "\n"
02665 " -host HOSTNAME : specify the host for afni communication\n"
02666 "\n"
02667 " e.g. -host mycomputer.dot.my.network\n"
02668 " e.g. -host 127.0.0.127\n"
02669 " e.g. -host mycomputer\n"
02670 " the default host is 'localhost'\n"
02671 "\n"
02672 " The specified HOSTNAME represents the machine that is\n"
02673 " running afni. Images will be sent to afni on this machine\n"
02674 " during the execution of '%s'.\n"
02675 "\n"
02676 " Note that the enviroment variable AFNI_TRUSTHOST must be\n"
02677 " set on the machine running afni. Set this equal to the\n"
02678 " name of the machine running Imon (so that afni knows to\n"
02679 " accept the data from the sending machine).\n"
02680 "\n"
02681 " -pause TIME_IN_MS : pause after each new volume\n"
02682 "\n"
02683 " e.g. -pause 200\n"
02684 "\n"
02685 " In some cases, the user may wish to slow down a real-time\n"
02686 " process. This option will cause a delay of TIME_IN_MS\n"
02687 " milliseconds after each volume is found.\n"
02688 "\n"
02689 " -rev_byte_order : pass the reverse of the BYTEORDER to afni\n"
02690 "\n"
02691 " Reverse the byte order that is given to afni. In case the\n"
02692 " detected byte order is not what is desired, this option\n"
02693 " can be used to reverse it.\n"
02694 "\n"
02695 " See the (obsolete) '-swap' option for more details.\n"
02696 "\n"
02697 " -rt_cmd COMMAND : send COMMAND(s) to realtime plugin\n"
02698 "\n"
02699 " e.g. -rt_cmd 'GRAPH_XRANGE 120'\n"
02700 " e.g. -rt_cmd 'GRAPH_XRANGE 120 \\n GRAPH_YRANGE 2.5'\n"
02701 "\n"
02702 " This option is used to pass commands to the realtime\n"
02703 " plugin. For example, 'GRAPH_XRANGE 120' will set the\n"
02704 " x-scale of the motion graph window to 120 (repetitions).\n"
02705 "\n"
02706 " Note: the command 'COMMAND' must be given in quotes, so\n"
02707 " that the shell will send it as a single parameter.\n"
02708 "\n"
02709 " Note: this option may be used multiple times.\n"
02710 "\n"
02711 " See README.realtime for more details.\n"
02712 "\n"
02713 " -swap (obsolete) : swap data bytes before sending to afni\n"
02714 "\n"
02715 " Since afni may be running on a different machine, the byte\n"
02716 " order may differ there. This option will force the bytes\n"
02717 " to be reversed, before sending the data to afni.\n"
02718 "\n"
02719 " ** As of version 3.0, this option should not be necessary.\n"
02720 " '%s' detects the byte order of the image data, and then\n"
02721 " passes that information to afni. The realtime plugin\n"
02722 " will (now) decide whether to swap bytes in the viewer.\n"
02723 "\n"
02724 " If for some reason the user wishes to reverse the order\n"
02725 " from what is detected, '-rev_byte_order' can be used.\n"
02726 "\n"
02727 " -zorder ORDER : slice order over time\n"
02728 "\n"
02729 " e.g. -zorder alt\n"
02730 " e.g. -zorder seq\n"
02731 " the default is 'alt'\n"
02732 "\n"
02733 " This options allows the user to alter the slice\n"
02734 " acquisition order in real-time mode, simliar to the slice\n"
02735 " pattern of the '-sp' option. The main differences are:\n"
02736 " o only two choices are presently available\n"
02737 " o the syntax is intentionally different (from that\n"
02738 " of 'to3d' or the '-sp' option)\n"
02739 "\n"
02740 " ORDER values:\n"
02741 " alt : alternating in the Z direction (over time)\n"
02742 " seq : sequential in the Z direction (over time)\n"
02743 "\n"
02744 " ---------------------------------------------------------------\n"
02745 " other options:\n"
02746 "\n"
02747 " -debug LEVEL : show debug information during execution\n"
02748 "\n"
02749 " e.g. -debug 2\n"
02750 " the default level is 1, the domain is [0,3]\n"
02751 " the '-quiet' option is equivalent to '-debug 0'\n"
02752 "\n"
02753 " -dicom_org : organize files before other processing\n"
02754 "\n"
02755 " e.g. -dicom_org\n"
02756 "\n"
02757 " When this flag is set, the program will attempt to read in\n"
02758 " all files subject to -infile_prefix or -infile_pattern,\n"
02759 " determine which are DICOM image files, and organize them\n"
02760 " into an ordered list of files per run.\n"
02761 "\n"
02762 " This may be necessary since the alphabetized list of files\n"
02763 " will not always match the sequential slice and time order\n"
02764 " (which means, for instance, that '*.dcm' may not list\n"
02765 " files in the correct order.\n"
02766 "\n"
02767 " In this case, if the DICOM files contain a valid 'image\n"
02768 " number' field (0x0020 0013), then they will be sorted\n"
02769 " before any further processing is done.\n"
02770 "\n"
02771 " Notes:\n"
02772 "\n"
02773 " - This does not work in real-time mode, since the files\n"
02774 " must all be organized before processing begins.\n"
02775 "\n"
02776 " - The DICOM images need valid 'image number' fields for\n"
02777 " organization to be possible (DICOM field 0x0020 0013).\n"
02778 "\n"
02779 " - This works will in conjunction with '-GERT_Reco', to\n"
02780 " create a script to make AFNI datasets. There will be\n"
02781 " a single file per run that contains the image filenames\n"
02782 " for that run (in order). This is fed to 'to3d'.\n"
02783 "\n"
02784 " -help : show this help information\n"
02785 "\n"
02786 " -hist : display a history of program changes\n"
02787 "\n"
02788 " -nice INCREMENT : adjust the nice value for the process\n"
02789 "\n"
02790 " e.g. -nice 10\n"
02791 " the default is 0, and the maximum is 20\n"
02792 " a superuser may use down to the minimum of -19\n"
02793 "\n"
02794 " A positive INCREMENT to the nice value of a process will\n"
02795 " lower its priority, allowing other processes more CPU\n"
02796 " time.\n"
02797 "\n"
02798 " -nt VOLUMES_PER_RUN : set the number of time points per run\n"
02799 "\n"
02800 " e.g. -nt 120\n"
02801 "\n"
02802 " With this option, if a run stalls before the specified\n"
02803 " VOLUMES_PER_RUN is reached (notably including the first\n"
02804 " run), the user will be notified.\n"
02805 "\n"
02806 " Without this option, %s will compute the expected number\n"
02807 " of time points per run based on the first run (and will\n"
02808 " allow the value to increase based on subsequent runs).\n"
02809 " Therefore %s would not detect a stalled first run.\n"
02810 "\n"
02811 " -quiet : show only errors and final information\n"
02812 "\n"
02813 " -quit : quit when there is no new data\n"
02814 "\n"
02815 " With this option, the program will terminate once a delay\n"
02816 " in new data occurs. This is most appropriate to use when\n"
02817 " the image files have already been collected.\n"
02818 "\n"
02819 " -start_file S_FILE : have %s process starting at S_FILE\n"
02820 "\n"
02821 " e.g. -start_file 043/I.901\n"
02822 "\n"
02823 " With this option, any earlier I-files will be ignored\n"
02824 " by %s. This is a good way to start processing a later\n"
02825 " run, if it desired not to look at the earlier data.\n"
02826 "\n"
02827 " In this example, all files in directories 003 and 023\n"
02828 " would be ignored, along with everything in 043 up through\n"
02829 " I.900. So 043/I.901 might be the first file in run 2.\n"
02830 "\n"
02831 " -use_imon : revert to Imon functionality\n"
02832 "\n"
02833 " -version : show the version information\n"
02834 "\n"
02835 " ---------------------------------------------------------------\n"
02836 " GERT_Reco options:\n"
02837 "\n"
02838 " -GERT_Reco : output a GERT_Reco_dicom script\n"
02839 "\n"
02840 " Create a script called 'GERT_Reco_dicom', similar to the\n"
02841 " one that Ifile creates. This script may be run to create\n"
02842 " the AFNI datasets corresponding to the I-files.\n"
02843 "\n"
02844 " -gert_outdir OUTPUT_DIR : set output directory in GERT_Reco\n"
02845 "\n"
02846 " e.g. -gert_outdir subject_A7\n"
02847 " e.g. -od subject_A7\n"
02848 " the default is '-gert_outdir .'\n"
02849 "\n"
02850 " This will add '-od OUTPUT_DIR' to the @RenamePanga command\n"
02851 " in the GERT_Reco script, creating new datasets in the\n"
02852 " OUTPUT_DIR directory, instead of the 'afni' directory.\n"
02853 "\n"
02854 " -sp SLICE_PATTERN : set output slice pattern in GERT_Reco\n"
02855 "\n"
02856 " e.g. -sp alt-z\n"
02857 " the default is 'alt+z'\n"
02858 "\n"
02859 " This options allows the user to alter the slice\n"
02860 " acquisition pattern in the GERT_Reco script.\n"
02861 "\n"
02862 " See 'to3d -help' for more information.\n"
02863 "\n"
02864 " ---------------------------------------------------------------\n"
02865 "\n"
02866 " Author: R. Reynolds - %s\n"
02867 "\n",
02868 prog, prog, prog, prog, prog, prog, prog,
02869 DIMON_VERSION
02870 );
02871
02872 return 0;
02873 }
02874 else if ( level == IFM_USE_HIST )
02875 {
02876 fputs( g_history, stdout );
02877 return 0;
02878 }
02879 else if ( level == IFM_USE_VERSION )
02880 {
02881 printf( "%s: %s, compile date: %s\n",
02882 prog, DIMON_VERSION, __DATE__ );
02883 return 0;
02884 }
02885
02886 fprintf( stderr, "error: usage() called with illegal level <%d>\n", level );
02887
02888 return -1;
02889 }
02890
02891
02892
02893
02894
02895
02896 static void hf_signal( int signum )
02897 {
02898 switch ( signum )
02899 {
02900 default :
02901 fprintf( stderr, "\nError: received unknown signal, %d\n",
02902 signum );
02903 break;
02904
02905 case SIGHUP :
02906 case SIGINT :
02907 case SIGTERM :
02908 show_run_stats( &gS );
02909 break;
02910 }
02911
02912 if(gD.level > 1) fprintf(stderr, "\n+d received signal, %d\n", signum);
02913
02914 if( gAC.state != ART_STATE_NO_USE )
02915 {
02916 if( gD.level > 1 )
02917 fprintf(stderr,"-d closing afni connection, state %d\n", gAC.state);
02918 ART_exit();
02919 }
02920
02921 fflush(stderr);
02922 fflush(stdout);
02923
02924 exit(0);
02925 }
02926
02927
02928
02929
02930
02931
02932 static int set_volume_stats( param_t * p, stats_t * s, vol_t * v )
02933 {
02934 run_t * rp;
02935
02936 if ( v == NULL || v->seq_num < 0 || v->run < 0 )
02937 {
02938 fprintf( stderr, "failure: SVS - insufficient data\n\n" );
02939 idisp_vol_t ( "-- VOLUME FAILURE INFO : ", v );
02940 }
02941
02942
02943 if ( s->nalloc == 0 )
02944 {
02945 s->runs = (run_t *)calloc( IFM_STAT_ALLOC, sizeof(run_t) );
02946 if ( s->runs == NULL )
02947 {
02948 fprintf( stderr, "failure: cannot allocate space for run info\n" );
02949 return -1;
02950 }
02951
02952
02953 s->slices = v->nim;
02954 s->z_first = v->z_first;
02955 s->z_last = v->z_last;
02956 s->z_delta = v->z_delta;
02957
02958 s->nalloc = IFM_STAT_ALLOC;
02959 s->nused = 0;
02960 s->nvols = gP.opts.nt;
02961
02962 if ( gD.level > 1 )
02963 fprintf( stderr, "\n-- svs: init alloc - vol %d, run %d, file %s\n",
02964 v->seq_num, v->run, v->first_file );
02965 }
02966
02967 if ( v->run >= s->nalloc )
02968 {
02969
02970 s->runs = (run_t *)realloc( s->runs, (v->run + IFM_STAT_ALLOC) *
02971 sizeof(run_t) );
02972 if ( s->runs == NULL )
02973 {
02974 fprintf( stderr, "failure: cannot realloc space for run info\n" );
02975 return -1;
02976 }
02977
02978 s->nalloc = v->run + IFM_STAT_ALLOC;
02979
02980
02981 memset( s->runs + s->nused, 0, (s->nalloc - s->nused)*sizeof(run_t) );
02982
02983 if ( gD.level > 1 )
02984 fprintf( stderr,
02985 "\n-- svs: realloc (%d entries) - vol %d, run %d, file %s\n",
02986 s->nalloc, v->seq_num, v->run, v->first_file );
02987
02988 }
02989
02990
02991
02992 rp = s->runs + v->run;
02993
02994 if ( s->nused < v->run+1 )
02995 s->nused = v->run+1;
02996
02997 if ( rp->volumes == 0 )
02998 {
02999 rp->f1index = v->fn_1;
03000 strncpy( rp->f1name, v->first_file, IFM_MAX_FLEN );
03001 }
03002
03003 rp->volumes = v->seq_num;
03004
03005
03006 if ( (p->opts.nt <= 0) && (s->nvols < v->seq_num) )
03007 s->nvols = v->seq_num;
03008
03009 if ( gD.level > 2 )
03010 fprintf( stderr, "\n-- svs: run %d, seq_num %d\n", v->run, v->seq_num );
03011
03012 return 0;
03013 }
03014
03015
03016
03017
03018
03019 static int create_gert_script( stats_t * s, param_t * p )
03020 {
03021
03022 if( p->opts.use_dicom ) return create_gert_dicom(s, p);
03023 else return create_gert_reco (s, &p->opts);
03024 }
03025
03026
03027
03028
03029
03030 static int create_gert_dicom( stats_t * s, param_t * p )
03031 {
03032 opts_t * opts = &p->opts;
03033 FILE * fp, * nfp;
03034 char * script = IFM_GERT_DICOM;
03035 char * spat;
03036 char outfile[32];
03037 int num_valid, c, findex;
03038
03039
03040 spat = opts->sp ? opts->sp : IFM_SLICE_PAT;
03041
03042 for ( c = 0, num_valid = 0; c < s->nused; c++ )
03043 if ( s->runs[c].volumes > 0 )
03044 num_valid++;
03045
03046 if ( num_valid == 0 )
03047 {
03048 fprintf( stderr, "-- no runs to use for '%s'\n", script );
03049 return 0;
03050 }
03051
03052
03053 for ( c = 0; c < s->nused; c++ )
03054 if ( s->runs[c].volumes > 0 )
03055 {
03056 }
03057
03058 if ( (fp = fopen( script, "w" )) == NULL )
03059 {
03060 fprintf( stderr, "failure: cannot open '%s' for writing, "
03061 "check permissions\n", script );
03062 return -1;
03063 }
03064
03065
03066 fprintf( fp,
03067 "#!/bin/tcsh\n"
03068 "\n"
03069 "# This script was automatically generated by '%s'.\n"
03070 "#\n"
03071 "# Please modify the following options for your own evil uses.\n"
03072 "\n"
03073 "set OutlierCheck = '' # use '-skip_outliers' to skip\n"
03074 "set OutPrefix = 'OutBrick' # prefix for datasets\n"
03075 "\n"
03076 "\n",
03077 IFM_PROG_NAME
03078 );
03079
03080 for ( c = 0; c < s->nused; c++ )
03081 if ( s->runs[c].volumes > 0 )
03082 {
03083
03084 sprintf(outfile, "dimon.files.run.%03d", c);
03085 if ( (nfp = fopen( outfile, "w" )) == NULL )
03086 {
03087 fprintf( stderr, "** DF: cannot open '%s' for writing",outfile);
03088 fclose(fp);
03089 return -1;
03090 }
03091
03092 for(findex = 0; findex < s->runs[c].volumes*s->slices; findex++)
03093 fprintf(nfp, "%s\n", p->fnames[s->runs[c].f1index+findex]);
03094 fclose(nfp);
03095
03096
03097 fprintf(fp, "to3d -prefix ${OutPrefix}_run_%03d \\\n"
03098 " -time:zt %d %d 0 %s \\\n"
03099 " -@ < %s\n\n",
03100 c, s->slices, s->runs[c].volumes, spat, outfile);
03101 }
03102
03103 fclose( fp );
03104
03105
03106 system( "chmod u+x " IFM_GERT_DICOM );
03107
03108 return 0;
03109 }
03110
03111
03112
03113
03114
03115
03116
03117
03118 static int create_gert_reco( stats_t * s, opts_t * opts )
03119 {
03120 FILE * fp;
03121 char * spat;
03122 char cdir[4], csuff[IFM_SUFFIX_LEN];
03123 int num_valid, c;
03124
03125
03126 spat = opts->sp ? opts->sp : IFM_SLICE_PAT;
03127
03128 for ( c = 0, num_valid = 0; c < s->nused; c++ )
03129 if ( s->runs[c].volumes > 0 )
03130 num_valid++;
03131
03132 if ( num_valid == 0 )
03133 {
03134 fprintf( stderr, "-- no runs to use for '%s'\n", IFM_GERT_SCRIPT );
03135 return 0;
03136 }
03137
03138 if ( (fp = fopen( IFM_GERT_SCRIPT, "w" )) == NULL )
03139 {
03140 fprintf( stderr, "failure: cannot open '%s' for writing, "
03141 "check permissions\n", IFM_GERT_SCRIPT );
03142 return -1;
03143 }
03144
03145
03146 fprintf( fp,
03147 "#!/bin/tcsh\n"
03148 "\n"
03149 "# This script was automatically generated by '%s'.\n"
03150 "# The script format was, uh, borrowed from Ziad's Ifile.c.\n"
03151 "#\n"
03152 "# Please modify the following options for your own evil uses.\n"
03153 "\n"
03154 "set OutlierCheck = '-oc' # use '' to skip outlier check\n"
03155 "set OutPrefix = 'OutBrick' # prefix for datasets\n"
03156 "set OutputDir = '-od %s' # where to put output datasets\n"
03157 "\n"
03158 "\n",
03159 IFM_PROG_NAME,
03160 opts->gert_outdir ? opts->gert_outdir : "afni"
03161 );
03162
03163 for ( c = 0; c < s->nused; c++ )
03164 if ( s->runs[c].volumes > 0 )
03165 {
03166 if ( path_to_dir_n_suffix(cdir, csuff, s->runs[c].f1name) < 0 )
03167 {
03168 fclose( fp );
03169 return -1;
03170 }
03171
03172 fprintf( fp, "@RenamePanga %s %s %d %d $OutPrefix "
03173 "-sp %s $OutlierCheck $OutputDir\n",
03174 cdir, csuff, s->slices, s->runs[c].volumes, spat );
03175 }
03176
03177 fputc( '\n', fp );
03178 fclose( fp );
03179
03180
03181 system( "chmod u+x " IFM_GERT_SCRIPT );
03182
03183 return 0;
03184 }
03185
03186
03187
03188
03189
03190
03191
03192 static int show_run_stats( stats_t * s )
03193 {
03194 int c;
03195
03196 if ( s == NULL )
03197 {
03198 fprintf( stderr, "failure, SRS - no stats struct!\n" );
03199 return -1;
03200 }
03201
03202 if ( s->nalloc <= 0 || s->nused <= 0 )
03203 return 0;
03204
03205 printf( "\n\n"
03206 "final run statistics:\n"
03207 " volume info :\n"
03208 " slices : %d\n"
03209 " z_first : %.4f\n"
03210 " z_last : %.4f\n"
03211 " z_delta : %.4f\n"
03212 "\n",
03213 s->slices, s->z_first, s->z_last, s->z_delta );
03214
03215 for ( c = 0; c < s->nused; c++ )
03216 {
03217 if ( s->runs[c].volumes > 0 )
03218 printf( " run #%4d : volumes = %3d, first file (#%d) = %s\n",
03219 c,s->runs[c].volumes,s->runs[c].f1index,s->runs[c].f1name);
03220 }
03221
03222 putchar( '\n' );
03223
03224 if ( gP.opts.gert_reco )
03225 (void)create_gert_script( s, &gP );
03226
03227 fflush( stdout );
03228
03229 return 0;
03230 }
03231
03232
03233
03234
03235
03236
03237 static int nap_time_from_tr( float tr )
03238 {
03239 float tr2 = 2 * tr;
03240 int nap_time;
03241
03242 if ( tr2 < 1 )
03243 return 1;
03244
03245 if ( tr2 > 10 )
03246 return 10;
03247
03248 nap_time = (int)(tr2 + 0.9);
03249
03250 if ( gD.level > 1 )
03251 fprintf(stderr,"-d computed nap_time is %d seconds (TR = %.2f)\n",
03252 nap_time, tr );
03253
03254 return( nap_time );
03255 }
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269 static int find_next_zoff( param_t * p, int start, float zoff )
03270 {
03271 int count;
03272
03273 if ( (p == NULL) || (start < 0) )
03274 return -2;
03275
03276 if ( start > p->nused )
03277 return -1;
03278
03279 for ( count = start; count <= p->nused; count++ )
03280 if ( fabs( zoff - p->flist[count].geh.zoff ) < IFM_EPSILON )
03281 return count;
03282
03283 return -1;
03284 }
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305 static int check_stalled_run ( int run, int seq_num, int naps, int nap_time )
03306 {
03307 static int func_failure = 0;
03308 static int prev_run = -1;
03309 static int prev_seq = -1;
03310
03311 if ( func_failure != 0 )
03312 return 0;
03313
03314 if ( ( run < 1 ) || ( seq_num < 1 ) || ( naps <= IFM_MAX_RUN_NAPS ) )
03315 return 0;
03316
03317
03318 if ( (((gS.nused + 1) < run) || (gS.runs[run].volumes < seq_num)) &&
03319 ( func_failure == 0 ) )
03320 {
03321 fprintf( stderr, "** warning: CSR - stats inconsistancy!\n" );
03322 func_failure = 1;
03323
03324 return -1;
03325 }
03326
03327 if ( seq_num < gS.nvols )
03328 {
03329
03330 if ( (run != prev_run) || (seq_num != prev_seq) )
03331 {
03332 fprintf( stderr, "\007\n"
03333 "****************************************************\n"
03334 "Warning: run seems to be stalled\n"
03335 "\n"
03336 " run : %d\n"
03337 " TRs completed : %d (of %d)\n"
03338 " approximate idle time : %d seconds\n"
03339 " first file of this run : %s\n"
03340 "****************************************************\n",
03341 run, seq_num, gS.nvols,
03342 naps*nap_time, gS.runs[run].f1name );
03343
03344 prev_run = run;
03345 prev_seq = seq_num;
03346
03347 return 2;
03348 }
03349 }
03350
03351 else if ( (run != prev_run) || (seq_num != prev_seq) )
03352 {
03353
03354 prev_run = run;
03355 prev_seq = seq_num;
03356
03357 return 1;
03358 }
03359
03360 return 0;
03361 }
03362
03363
03364
03365
03366
03367 unsigned long l_THD_filesize( char * pathname )
03368 {
03369 static struct stat buf ; int ii ;
03370
03371 if( pathname == NULL ) return -1 ;
03372 ii = stat( pathname , &buf ) ; if( ii != 0 ) return -1 ;
03373
03374 return buf.st_size ;
03375 }
03376
03377
03378
03379
03380
03381
03382
03383
03384
03385 static int check_im_store_space( im_store_t * is, int num_images )
03386 {
03387 if ( (is == NULL) || (num_images <= 0) )
03388 {
03389 fprintf( stderr, "** CISS: invalid parameters (%p,%d)\n",
03390 is, num_images );
03391 return -1;
03392 }
03393
03394 if ( is->ary_len >= num_images )
03395 return 0;
03396
03397
03398
03399 if ( gD.level > 2 )
03400 fprintf( stderr, "++ allocating %d image pointers (was %d)\n",
03401 num_images, is->ary_len );
03402
03403 is->im_ary = realloc(is->im_ary, num_images * sizeof(void *));
03404
03405 if ( is->im_ary == NULL )
03406 {
03407 fprintf( stderr, "** failure: cannot allocate %d image pointers\n",
03408 num_images );
03409 return -1;
03410 }
03411
03412
03413 memset(is->im_ary+is->ary_len, 0, (num_images-is->ary_len)*sizeof(void*));
03414
03415 is->ary_len = num_images;
03416
03417 return 1;
03418 }
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428 static int alloc_x_im( im_store_t * is, int bytes )
03429 {
03430 if ( (is == NULL) || (bytes <= 0) )
03431 {
03432 fprintf( stderr, "** bad params to AXI (%p,%d)\n", is, bytes );
03433 return -1;
03434 }
03435
03436 is->im_size = bytes;
03437
03438 if ( (is->x_im = malloc( bytes )) == NULL )
03439 {
03440 fprintf( stderr, "** AXI: failed to malloc %d bytes for x_im\n",
03441 bytes );
03442 return -1;
03443 }
03444
03445 if ( gD.level > 1 )
03446 fprintf( stderr, "++ allocating %d bytes for is->x_im\n", bytes );
03447
03448 return 0;
03449 }
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462 static int check_im_byte_order( int * order, vol_t * v, param_t * p )
03463 {
03464 int one = 1;
03465
03466 if ( (order == NULL) || (v == NULL) || (p == NULL) )
03467 {
03468 fprintf( stderr, "** invalid paramters to CIBO (%p,%p,%p)\n",
03469 order, v, p );
03470 return -1;
03471 }
03472
03473
03474 *order = (*(char *)&one == 1) ? LSB_FIRST : MSB_FIRST;
03475
03476 if ( gD.level > 1 )
03477 fprintf( stderr, "-- system order is %s, ",
03478 (*order == MSB_FIRST) ? "MSB_FIRST" : "LSB_FIRST" );
03479
03480
03481 if ( p->flist[v->fl_1].gex.swap ^ p->opts.rev_bo )
03482 *order = LSB_FIRST + MSB_FIRST - *order;
03483
03484 if ( gD.level > 1 )
03485 fprintf( stderr, "image order is %s\n",
03486 (*order == MSB_FIRST) ? "MSB_FIRST" : "LSB_FIRST" );
03487
03488 return 0;
03489 }
03490
03491
03492
03493
03494
03495
03496
03497
03498
03499
03500
03501
03502
03503
03504 static int complete_orients_str( vol_t * v, param_t * p )
03505 {
03506 int kk;
03507
03508 if ( (v == NULL) || (p == NULL) )
03509 {
03510 fprintf( stderr, "** invalid paramters to COS (%p,%p)\n", v, p );
03511 return -1;
03512 }
03513
03514 if ( gD.level > 2 )
03515 fprintf(stderr,"completing orients from '%s' to", v->geh.orients);
03516
03517 if ( p->ftype == IFM_IM_FTYPE_DICOM )
03518 strncpy(v->geh.orients + 4, DI_MRL_orients + 4, 2 );
03519 else
03520 {
03521 kk = p->flist[v->fl_1].gex.kk;
03522
03523 switch( kk )
03524 {
03525 case 1:
03526 if ( v->z_delta > 0 )
03527 {
03528 v->geh.orients[4] = 'L';
03529 v->geh.orients[5] = 'R';
03530 }
03531 else
03532 {
03533 v->geh.orients[4] = 'R';
03534 v->geh.orients[5] = 'L';
03535 }
03536 break;
03537
03538 case 2:
03539 if ( v->z_delta > 0 )
03540 {
03541 v->geh.orients[4] = 'P';
03542 v->geh.orients[5] = 'A';
03543 }
03544 else
03545 {
03546 v->geh.orients[4] = 'A';
03547 v->geh.orients[5] = 'P';
03548 }
03549 break;
03550
03551 case 3:
03552 if ( v->z_delta > 0 )
03553 {
03554 v->geh.orients[4] = 'I';
03555 v->geh.orients[5] = 'S';
03556 }
03557 else
03558 {
03559 v->geh.orients[4] = 'S';
03560 v->geh.orients[5] = 'I';
03561 }
03562 break;
03563
03564 default:
03565 {
03566 fprintf(stderr, "** COS failure: kk (%d) not in [1,3]\n", kk);
03567 return -1;
03568 }
03569 }
03570 }
03571
03572 v->geh.orients[6] = '\0';
03573
03574 if ( gD.level > 2 ) fprintf(stderr,"'%s'\n", v->geh.orients);
03575
03576 return 0;
03577 }
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589 static int find_fl_file_index( param_t * p )
03590 {
03591 char ** nlp;
03592 char * sd, * sf;
03593 int index, found = 0;
03594 int dlen;
03595
03596 if ( ! p || (! p->opts.start_file && ! p->opts.start_dir) )
03597 return 0;
03598
03599 sd = p->opts.start_dir;
03600 sf = p->opts.start_file;
03601
03602 if ( gD.level > 2 )
03603 fprintf(stderr,"-d searching for initial dir, file: %s, %s\n",
03604 sd ? sd : "<no start_dir>", sf ? sf : "<no start_file>");
03605
03606 index = 0;
03607 nlp = p->fnames;
03608
03609 if ( sd )
03610 {
03611 dlen = strlen(sd);
03612 for ( ; index < p->nfiles; index++, nlp++ )
03613 if ( ! strncmp(*nlp, sd, dlen) ) { found = 1; break; }
03614 }
03615
03616 if ( sf )
03617 {
03618 found = 0;
03619 for ( ; index < p->nfiles; index++, nlp++ )
03620 if ( ! strcmp(*nlp, sf) ) { found = 1; break; }
03621 }
03622
03623 if ( gD.level > 2 )
03624 {
03625 if(found) fprintf(stderr,"-d found match at entry %d: %s\n",index,*nlp);
03626 else fprintf(stderr,"-d no match found (yet)...\n");
03627 }
03628
03629 if ( found ) return index;
03630 else return -1;
03631 }
03632
03633
03634
03635
03636
03637 static int str_char_count( char * str, int len, char target )
03638 {
03639 char * cp;
03640 char * last = str + len;
03641 int num = 0;
03642
03643 if ( (str == NULL) || (len <= 0) )
03644 return 0;
03645
03646 for ( cp = str; cp < last; cp++ )
03647 if ( *cp == target )
03648 num++;
03649
03650 return num;
03651 }
03652
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665 static int path_to_dir_n_suffix( char * dir, char * suff, char * path )
03666 {
03667 char * cp, *cp2;
03668
03669 if ( (dir == NULL) || (suff == NULL) || (path == NULL) )
03670 {
03671 fprintf( stderr, "failure: PTDNS - invalid params (%p,%p,%p)\n",
03672 dir, suff, path );
03673 return -1;
03674 }
03675
03676
03677 for ( cp = path + strlen(path) - 1; (*cp != '.') && (cp > path); cp-- )
03678 ;
03679
03680 if ( *cp != '.' )
03681 {
03682 fprintf( stderr, "failure: cannot find suffix in '%s'\n", path );
03683 return -1;
03684 }
03685 else if ( strlen( cp ) > IFM_SUFFIX_LEN )
03686 {
03687 fprintf( stderr, "failure: suffix too long in '%s'\n", path );
03688 return -1;
03689 }
03690
03691 strcpy( suff, cp+1 );
03692
03693
03694 for ( cp2 = suff; (*cp2 != '\0') && isdigit(*cp2); cp2++ )
03695 ;
03696
03697 if ( *cp2 != '\0' )
03698 {
03699 fprintf( stderr, "failure: suffix not integer in '%s'\n", path );
03700 return -1;
03701 }
03702
03703
03704 cp -= 5;
03705 if ( ( cp < path ) ||
03706 ( ! isdigit( cp[0] ) ) ||
03707 ( ! isdigit( cp[1] ) ) ||
03708 ( ! isdigit( cp[2] ) ) ||
03709 ( cp[3] != '/' ) ||
03710 ( cp[4] != 'I' ) )
03711 {
03712 fprintf( stderr, "failure: PTDNS - ill-formed path '%s'\n", path );
03713 return -1;
03714 }
03715
03716
03717 strncpy( dir, cp, 3 );
03718 dir[3] = '\0';
03719
03720 return 0;
03721 }
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731 static int add_to_string_list( string_list * list, char * str )
03732 {
03733 if ( !list || !str )
03734 return -1;
03735
03736
03737 if ( list->nalloc == 0 || (list->nalloc <= list->nused) )
03738 {
03739 list->nalloc += 10;
03740 list->str = (char **)realloc(list->str, list->nalloc*sizeof(char *));
03741 if ( !list->str )
03742 {
03743 fprintf(stderr,"** failed to allocate for %d (char *)s\n",
03744 list->nalloc);
03745 return -1;
03746 }
03747 if( gD.level > 2 )
03748 fprintf(stderr,"+d realloc %d (char *)'s\n",list->nalloc);
03749 }
03750
03751 list->str[list->nused] = str;
03752 list->nused++;
03753
03754 return 0;
03755 }
03756
03757
03758
03759
03760
03761
03762 static int empty_string_list( string_list * list, int free_mem )
03763 {
03764 if ( list->str && free_mem )
03765 free( list->str );
03766
03767 list->str = NULL;
03768 list->nalloc = 0;
03769 list->nused = 0;
03770
03771 return 0;
03772 }
03773
03774