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