00001 
00002 #include <stdio.h>
00003 #include <math.h>
00004 
00005 #include "thd_iochan.h"
00006 #include "Imon.h"
00007 #include "realtime.h"
00008 
00009 extern ART_comm  gAC;
00010 
00011 
00012 static char orient_side_rai( float coord, char dir );
00013 
00014 
00015 
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 int ART_start_io( ART_comm * ac, int debug )
00047 
00048 {
00049    int ii ;
00050 
00051    
00052 
00053    if( ac->mode <= 0 || ac->mode == AFNI_CONTINUE_MODE ) return 0 ;
00054 
00055    
00056 
00057 
00058    if( ac->mode == AFNI_OPEN_CONTROL_MODE ){
00059 
00060       sprintf( ac->ioc_name , "tcp:%s:%d" , ac->host , AFNI_CONTROL_PORT ) ;
00061 
00062       if( debug > 1 )
00063          fprintf(stderr,"Opening control channel %s to AFNI.\n",ac->ioc_name) ;
00064 
00065       ac->ioc = iochan_init( ac->ioc_name , "w" ) ;
00066 
00067       if( ac->ioc == NULL ){
00068          fprintf(stderr,"Can't open control channel %s to AFNI!\a\n",
00069                  ac->ioc_name) ;
00070          return -1;
00071       } else {
00072          if( debug > 1 )
00073              fprintf(stderr,"Entering AFNI_WAIT_CONTROL_MODE.\n") ;
00074 
00075          
00076          ac->mode = AFNI_WAIT_CONTROL_MODE ;
00077       }
00078    }
00079 
00080    
00081 
00082    if( ac->mode == AFNI_WAIT_CONTROL_MODE ){
00083 
00084       ii = iochan_writecheck( ac->ioc , 1 ) ;  
00085 
00086 
00087 
00088 
00089       if( ii < 0 ){
00090          fprintf(stderr,"Control channel to AFNI failed!\n") ;
00091          IOCHAN_CLOSENOW(ac->ioc) ;
00092          ac->mode = 0 ;                    
00093          return -1;
00094       } else if( ii > 0 ){
00095          if( debug > 1 )
00096          {
00097             fprintf(stderr,"Control channel connected to AFNI.");
00098             fprintf(stderr,"  Entering AFNI_OPEN_DATA_MODE.\n") ;
00099          }
00100 
00101          ac->mode = AFNI_OPEN_DATA_MODE ;  
00102       }
00103    }
00104 
00105    
00106 
00107 
00108 
00109    if( ac->mode == AFNI_OPEN_DATA_MODE ){
00110 
00111       
00112 
00113       if ( ac->use_tcp )
00114          sprintf(ac->ioc_name,"tcp:%s:%d",ac->host,AFNI_TCP_PORT) ;
00115 
00116       strcpy(ac->buf, ac->ioc_name) ;     
00117 
00118       if( debug > 1 )
00119          fprintf(stderr,"Sending control information to AFNI:\n%s\n",ac->buf) ;
00120 
00121       ii = iochan_sendall( ac->ioc , ac->buf , strlen(ac->buf)+1 ) ;
00122 
00123 
00124 
00125       if( ii < 0 ){
00126          fprintf(stderr,"Transmission of control data to AFNI failed!\a\n") ;
00127          IOCHAN_CLOSENOW(ac->ioc) ;
00128          ac->mode = 0 ;
00129          return -1;
00130       } else {
00131          
00132          while( ! iochan_clearcheck(ac->ioc,2) )
00133             iochan_sleep(2) ;
00134          IOCHAN_CLOSENOW(ac->ioc) ;                 
00135 
00136          if( debug > 1 )
00137             fprintf(stderr,"Opening data channel %s to AFNI.\n",ac->ioc_name) ;
00138 
00139          ac->ioc = iochan_init( ac->ioc_name , "w" ) ; 
00140          if( ac->ioc == NULL ){
00141             fprintf(stderr,"Can't open data channel %s to AFNI!\a\n",
00142                     ac->ioc_name) ;
00143             ac->mode = 0 ;
00144             return -1;
00145          } else {
00146             if( debug > 1 ) fprintf(stderr,"Entering AFNI_CATCHUP_MODE.\n") ;
00147             ac->mode = AFNI_CATCHUP_MODE ;
00148          }
00149       }
00150    }
00151 
00152    
00153 
00154 
00155    if( ac->mode == AFNI_CATCHUP_MODE ){
00156 
00157       ii = iochan_writecheck( ac->ioc , 1 ) ;  
00158       if( ii < 0 ){
00159          fprintf(stderr,
00160                  "AFNI data channel aborted before any data was sent!\a\n") ;
00161          IOCHAN_CLOSENOW(ac->ioc) ;
00162          ac->mode = 0 ;
00163          return -1;
00164       } else if( ii > 0 ){                      
00165          ac->mode = AFNI_CONTINUE_MODE ;
00166 
00167         if ( debug > 1 )
00168             fprintf(stderr,"Entering AFNI_CONTINUE_MODE.\n");
00169       }
00170    }
00171 
00172    return 0;
00173 }
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 int ART_send_end_of_run( ART_comm * ac, int run, int seq, int debug )
00183 {
00184     static int   prev_run = -1;
00185     static int   prev_seq = -1;
00186     char       * image;
00187 
00188     if ( ac->state != ART_STATE_IN_USE )
00189         return 0;
00190 
00191     if ( (run != prev_run) || (seq != prev_seq) )
00192     {
00193         prev_run = run;
00194         prev_seq = seq;
00195 
00196         image = (char *)ac->param->im_store.x_im;
00197 
00198         if ( image == NULL )
00199         {
00200             fprintf( stderr, "** failure: x_im is NULL\n"
00201                              "   - closing afni connection\n" );
00202 
00203             ac->state = ART_STATE_NO_USE;
00204             ART_exit();
00205             return -1;
00206         }
00207 
00208         strcpy( image, ART_COMMAND_MARKER );
00209         image[ART_COMMAND_MARKER_LEN] = '\0';
00210 
00211         if ( iochan_sendall( ac->ioc, image, ac->param->im_store.im_size ) < 0 )
00212         {
00213             fprintf( stderr, "** failed to transmit EOR to afni @ %s\n"
00214                              "   - closing afni connection\n", ac->host );
00215 
00216             ac->state = ART_STATE_NO_USE;
00217             ART_exit();
00218             return -1;
00219         }
00220 
00221         if ( debug > 1 )
00222             fprintf( stderr, "-- EOR: end of run signal (%d,%d)\n", run, seq );
00223 
00224         
00225         ac->state = ART_STATE_TO_SEND_CTRL;
00226 
00227         iochan_sleep(50);                         
00228 
00229         return 1;
00230     }
00231 
00232     return 0;
00233 }
00234 
00235 
00236 
00237 
00238 
00239 
00240 int ART_send_volume( ART_comm * ac, vol_t * v, int debug )
00241 {
00242     char * image;
00243     int    slice, bytes;
00244 
00245     if ( ac == NULL || v == NULL )
00246     {
00247         fprintf( stderr, "failure: ASV called with invalid arguments!\n" );
00248         return -1;
00249     }
00250 
00251     if ( ac->state != ART_STATE_IN_USE )
00252         return 0;
00253 
00254     
00255 
00256     bytes = ac->param->im_store.im_size;
00257 
00258     for ( slice = 0; slice < v->nim; slice++ )
00259     {
00260         image = (char *)ac->param->im_store.im_ary[v->fl_1 + slice];
00261 
00262         if ( ac->swap )              
00263             swap_2( image, bytes/2 );
00264 
00265         if ( iochan_sendall( ac->ioc, image, bytes ) < 0 )
00266         {
00267             fprintf( stderr, "** failed to transmit data to afni @ %s\n"
00268                              "   - closing afni connection\n", ac->host );
00269 
00270             ac->state = ART_STATE_NO_USE;
00271             ART_exit();
00272             return -1;
00273         }
00274     }
00275 
00276     if ( debug > 2 )
00277         fprintf( stderr, "++ sent images from volume (%d:%d) to host %s\n",
00278                  v->run, v->seq_num, ac->host );
00279 
00280     return 0;
00281 }
00282 
00283 
00284 
00285 
00286 
00287 
00288 int ART_open_afni_link( ART_comm * ac, int num_tries, int again, int debug )
00289 {
00290     int rv = 0, count;
00291 
00292     if ( ac == NULL )
00293         return -1;
00294 
00295     if ( debug > 1 )
00296         fprintf( stderr, "-- starting I/O to afni\n" );
00297 
00298     if ( ac->state != ART_STATE_TO_OPEN )
00299         return 0;
00300 
00301     for ( count = 0;
00302           (count < num_tries) && (rv == 0) && (ac->mode != AFNI_CONTINUE_MODE);
00303           count++ )
00304     {
00305         rv = ART_start_io( ac, debug );
00306         iochan_sleep(100);              
00307     }
00308 
00309     if ( ac->mode == AFNI_CONTINUE_MODE )       
00310     {
00311         if ( debug > 0 )
00312             fprintf( stderr, "++ comm link to afni established at <%s>\n",
00313                      ac->host );
00314         ac->state = ART_STATE_TO_SEND_CTRL;
00315     }
00316     else if ( (rv == 0) && again )
00317     {
00318         if ( debug > 0 )
00319         {
00320             fprintf( stderr, "** failed to connect to afni at '%s' - "
00321                      "will try again later\n", ac->host );
00322         }
00323     }
00324     else                        
00325     {
00326         fprintf( stderr, "** failed to connect to afni at '%s' - "
00327                  "GIVING UP!\n", ac->host );
00328         ac->state = ART_STATE_NO_USE;
00329     }
00330 
00331     return rv;
00332 }
00333 
00334 
00335 
00336 
00337 
00338 
00339 int ART_init_AC_struct( ART_comm * ac )
00340 {
00341     if ( ac == NULL )
00342         return -1;
00343 
00344     ac->state       = ART_STATE_NO_USE;
00345     ac->mode        = 0;
00346     ac->use_tcp     = 1;
00347     ac->swap        = 0;
00348     ac->zorder      = NULL;
00349     strcpy( ac->host, "localhost" );
00350     ac->ioc_name[0] = '\0';
00351     ac->ioc         = NULL;
00352     ac->param       = NULL;
00353 
00354     return 0;
00355 }
00356 
00357 
00358 
00359 
00360 
00361 
00362 int ART_send_control_info( ART_comm * ac, vol_t * v, int debug )
00363 {
00364     char tbuf[ART_TBUF_LEN];          
00365     int  rv;
00366 
00367     if ( (ac == NULL) || (v == NULL) )
00368     {
00369         fprintf( stderr, "failure: ASCI called with invalid parameters\n" );
00370         ac->state = ART_STATE_NO_USE;
00371         return -1;
00372     }
00373 
00374     if ( (ac->state != ART_STATE_TO_SEND_CTRL) ||
00375          (ac->mode  != AFNI_CONTINUE_MODE) )
00376         return 0;
00377 
00378     ac->buf[0] = '\0';                      
00379 
00380     
00381     strcpy( tbuf, "ACQUISITION_TYPE 2D+zt" );
00382     ART_ADD_TO_BUF( ac->buf, tbuf );
00383 
00384     
00385     if ( ac->zorder )
00386         sprintf( tbuf, "ZORDER %s", ac->zorder);
00387     else
00388         strcpy( tbuf, "ZORDER seq" );   
00389     ART_ADD_TO_BUF( ac->buf, tbuf );
00390 
00391     
00392     if ( ac->param->opts.sp )
00393     {
00394         sprintf( tbuf, "TPATTERN %s", ac->param->opts.sp );
00395         ART_ADD_TO_BUF( ac->buf, tbuf );
00396     }
00397 
00398     
00399     sprintf( tbuf, "TR %f", v->geh.tr );
00400     ART_ADD_TO_BUF( ac->buf, tbuf );
00401 
00402     
00403     sprintf( tbuf, "XYFOV %f %f %f", fabs(v->geh.nx * v->geh.dx),
00404                                      fabs(v->geh.ny * v->geh.dy),
00405                                      fabs(v->nim    * v->z_delta) );
00406     ART_ADD_TO_BUF( ac->buf, tbuf );
00407 
00408     
00409     sprintf( tbuf, "XYMATRIX %d %d %d", v->geh.nx, v->geh.ny, v->nim );
00410     ART_ADD_TO_BUF( ac->buf, tbuf );
00411 
00412     
00413     strcpy( tbuf, "DATUM short" );
00414     ART_ADD_TO_BUF( ac->buf, tbuf );
00415 
00416     
00417     sprintf( tbuf, "XYZAXES %c-%c %c-%c %c-%c",
00418                            v->geh.orients[0], v->geh.orients[1],
00419                            v->geh.orients[2], v->geh.orients[3],
00420                            v->geh.orients[4], v->geh.orients[5] );
00421     ART_ADD_TO_BUF( ac->buf, tbuf );
00422 
00423     
00424     
00425     if( ac->param->ftype == IFM_IM_FTYPE_GEMS5 )
00426     {
00427         char o0 = v->geh.orients[0];    
00428         char o2 = v->geh.orients[2];
00429         char o4 = v->geh.orients[4];
00430         int  sx, sy, sz;                
00431 
00432         
00433         
00434 
00435         
00436 
00437         
00438         if ( o0 == 'L' || o0 == 'P' || o0 == 'I' ) sx = -1; else sx = 1;
00439         if ( o2 == 'L' || o2 == 'P' || o2 == 'I' ) sy = -1; else sy = 1;
00440         if ( o4 == 'L' || o4 == 'P' || o4 == 'I' ) sz = -1; else sz = 1;
00441 
00442         
00443         sprintf(tbuf,"XYZFIRST %f %f %f",
00444             sx * v->gex.xorg - v->geh.dx/2.0,
00445             sy * v->gex.yorg - v->geh.dy/2.0,
00446             sz * v->z_first );
00447 
00448         ART_ADD_TO_BUF( ac->buf, tbuf );
00449     }
00450     else if( ac->param->ftype == IFM_IM_FTYPE_DICOM )  
00451     {
00452         char o0 = v->geh.orients[0];    
00453         char o2 = v->geh.orients[2];
00454         char o4 = v->geh.orients[4];
00455 
00456         
00457         
00458 
00459         sprintf(tbuf,"XYZFIRST %f%c %f%c %f%c",
00460                 fabs(v->gex.xorg), orient_side_rai(v->gex.xorg, o0),
00461                 fabs(v->gex.yorg), orient_side_rai(v->gex.yorg, o2),
00462                 fabs(v->z_first),  orient_side_rai(v->z_first,  o4));
00463         ART_ADD_TO_BUF( ac->buf, tbuf );
00464     }
00465 
00466     
00467     if ( ! ac->swap )
00468     {
00469         sprintf( tbuf, "BYTEORDER %s", (ac->byte_order == LSB_FIRST) ?
00470                  "LSB_FIRST" : "MSB_FIRST" );
00471         ART_ADD_TO_BUF( ac->buf, tbuf );
00472     }
00473 
00474     
00475     {
00476         char * graph_win;                       
00477         char * image_win;                       
00478         char   o4 = v->geh.orients[4];          
00479         int    nt = ac->param->opts.nt;         
00480 
00481         if ( (o4 == 'R') || (o4 == 'r') || (o4 == 'L') || (o4 == 'l') )
00482         {
00483             graph_win = "sagittalgraph";
00484             image_win = "sagittalimage";
00485         }
00486         else if ( (o4 == 'I') || (o4 == 'i') || (o4 == 'S') || (o4 == 's') )
00487         {
00488             graph_win = "axialgraph";
00489             image_win = "axialimage";
00490         }
00491         else
00492         {
00493             graph_win = "coronalgraph";
00494             image_win = "coronalimage";
00495         }
00496         
00497         
00498         sprintf(tbuf, "DRIVE_AFNI OPEN_WINDOW %s\n"
00499                       "DRIVE_AFNI OPEN_WINDOW %s", image_win, graph_win );
00500 
00501         if ( nt > 0 )
00502             sprintf( tbuf+strlen(tbuf), " pinnum=%d", nt );
00503 
00504         ART_ADD_TO_BUF( ac->buf, tbuf );
00505     }
00506 
00507     
00508     if ( ac->param->opts.rt_list.str )
00509     {
00510         string_list * list = &ac->param->opts.rt_list;
00511         char        * cp;
00512         int           ns;
00513 
00514         for ( ns = 0; ns < list->nused; ns++ )
00515         {
00516             strncpy( tbuf, list->str[ns], 256 );
00517 
00518             
00519             for ( cp = tbuf; cp < (tbuf + strlen(tbuf) - 1); cp++ )
00520                 if ( cp[0] == '\\' && cp[1] == 'n' )
00521                 {
00522                     cp[0] = ' ';
00523                     cp[1] = '\n';
00524                     cp++;
00525                 }
00526 
00527             ART_ADD_TO_BUF( ac->buf, tbuf );
00528         }
00529     }
00530 
00531     
00532     if ( ac->param->opts.drive_list.str )
00533     {
00534         string_list * list = &ac->param->opts.drive_list;
00535         char        * cp;
00536         int           ns;
00537 
00538         for ( ns = 0; ns < list->nused; ns++ )
00539         {
00540             sprintf( tbuf, "DRIVE_AFNI %s", list->str[ns] );
00541 
00542             
00543             for ( cp = tbuf; cp < (tbuf + strlen(tbuf) - 1); cp++ )
00544                 if ( cp[0] == '\\' && cp[1] == 'n' )
00545                 {
00546                     cp[0] = ' ';
00547                     cp[1] = '\n';
00548                     cp++;
00549                 }
00550 
00551             ART_ADD_TO_BUF( ac->buf, tbuf );
00552         }
00553     }
00554 
00555     
00556     {
00557         int count, len, tot_len;
00558 
00559         
00560         sprintf( tbuf, "NOTE created remotely via real-time afni\f"
00561                  "    starting with file : '%s'\f"
00562                  "    creation command   :",
00563                  v->first_file );
00564         tot_len = strlen( tbuf );
00565 
00566         for ( count = 0; count < ac->param->opts.argc; count++ )
00567         {
00568             len = strlen( ac->param->opts.argv[count] );
00569 
00570             
00571             if ( tot_len + len + 5 >= ART_TBUF_LEN )
00572             {
00573                 strcat( tbuf, " ..." );
00574                 break;
00575             }
00576 
00577             strcat( tbuf, " " );
00578             strcat( tbuf, ac->param->opts.argv[count] );
00579         }
00580         
00581         ART_ADD_TO_BUF( ac->buf, tbuf );
00582     }
00583 
00584     if ( debug > 1 )
00585         fprintf( stderr, "++ dataset control info for afni:\n   %s", ac->buf );
00586     if ( (debug > 0) && (strlen(ac->buf) > (ART_TBUF_LEN * 0.8)) )
00587         fprintf(stderr,"** warning: ac->buf len uses %d of %d bytes\n",
00588                 (int)strlen(ac->buf), ART_TBUF_LEN);
00589 
00590     rv = iochan_sendall( ac->ioc, ac->buf, strlen(ac->buf)+1 );
00591 
00592     if ( rv < 0 )
00593     {
00594         fprintf( stderr, "** failure to send control info to afni\n" );
00595         ac->state = ART_STATE_NO_USE;
00596 
00597         return -1;
00598     }
00599 
00600     ac->state = ART_STATE_IN_USE;                 
00601 
00602     iochan_sleep(50);                             
00603 
00604     return 0;
00605 }
00606 
00607 
00608 
00609 
00610 
00611 
00612 void ART_exit( void )
00613 {
00614     static int been_here = 0;           
00615 
00616     if ( been_here == 0 )
00617     {
00618         iochan_close(gAC.ioc);
00619         fprintf( stderr, "ART_exit: closing afni control channel\n" );
00620         been_here = 1;
00621     }
00622 
00623     return;
00624 }
00625 
00626 
00627 
00628 
00629 
00630 
00631 int ART_idisp_ART_comm( char * info, ART_comm * ac )
00632 {
00633     if ( info )
00634         fputs( info, stdout );
00635 
00636     if ( ac == NULL )
00637     {
00638         printf( "ART_idisp_ART_comm: ac == NULL\n" );
00639         return -1;
00640     }
00641 
00642     printf( "ART_comm struct at %p :\n"
00643             "   (state, mode)   = (%d, %d)\n"
00644             "   (use_tcp, swap) = (%d, %d)\n"
00645             "   byte_order      = %d\n"
00646             "   zorder          = %s\n"
00647             "   host            = %s\n"
00648             "   ioc_name        = %s\n"
00649             "   (ioc, param)    = (0x%p, 0x%p)\n",
00650             ac, ac->state, ac->mode, ac->use_tcp, ac->swap, ac->byte_order,
00651             CHECK_NULL_STR(ac->zorder), CHECK_NULL_STR(ac->host),
00652             CHECK_NULL_STR(ac->ioc_name), ac->ioc, ac->param );
00653 
00654     return 0;
00655 }
00656 
00657 
00658 
00659 
00660 
00661 
00662 int swap_2( void * ptr, int npairs )
00663 {
00664     unsigned char * addr = ptr;
00665     int             count;
00666 
00667     for ( count = 0; count < npairs; count++ )
00668     {
00669         addr[0] ^= addr[1]; addr[1] ^= addr[0]; addr[0] ^= addr[1];
00670         addr += 2;
00671     }
00672 
00673     return 0;
00674 }
00675 
00676 
00677 
00678 
00679 static char orient_side_rai( float coord, char dir )
00680 {
00681     int d = toupper(dir);
00682 
00683     if ( d == 'R' || d == 'L' ) return( coord < 0 ? 'R' : 'L' );
00684     if ( d == 'A' || d == 'P' ) return( coord < 0 ? 'A' : 'P' );
00685     if ( d == 'I' || d == 'S' ) return( coord < 0 ? 'I' : 'S' );
00686 }
00687