Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

plugout_tt.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002    Major portions of this software are copyrighted by the Medical College
00003    of Wisconsin, 1994-2000, and are released under the Gnu General Public
00004    License, Version 2.  See the file README.Copyright for details.
00005 ******************************************************************************/
00006    
00007 /***************************************************************
00008   Sample plugout program, that registers with AFNI
00009   to be notified every time the Talairach-Tournoux
00010   coordinates change.  Note that this will only
00011   occur when the lowest numbered active AFNI
00012   controller is in the Talairach view.
00013   T-T coordinates are
00014       -x axis = L   +x axis = R
00015       -y axis = P   +y axis = A
00016       -z axis = I   +z axis = S
00017   Note that x and y are each flipped from the
00018   DICOM standard, which AFNI uses internally.
00019   The values reported to this plugout program
00020   are in the T-T system, not the DICOM system.
00021                                           RWCox, June 1997
00022 ****************************************************************
00023   Usage: plugout_tt [-host name] [-v]
00024   Options:
00025     -host name  Means to connect to AFNI running on the
00026                   remote computer 'name'.  The default is
00027                   to connect on the current host.  If the
00028                   connection is to "localhost" (the default),
00029                   then shared memory is used, otherwise
00030                   a TCP/IP socket is used.
00031     -v          Verbose mode: prints out lots of stuff.
00032 
00033   Note that AFNI must be run with the "-yesplugouts"
00034   option to allow it to talk to this program.  See the
00035   output of "afni -help" for (a little) more information.
00036 ****************************************************************
00037   The file "thd_trusthost" controls which systems are
00038   allowed to connect to AFNI.  This is controlled by
00039   setting the environment variables
00040     AFNI_TRUSTHOST_1 through AFNI_TRUSTHOST_99
00041   to the IP addresses (not names) of hosts from which
00042   AFNI should accept plugout connections.  For example,
00043     setenv AFNI_TRUSTHOST_1 123.45.67.89
00044   Note that 127.0.0.1 (localhost) is always trusted.
00045 ****************************************************************
00046   Compilation:
00047     If using the Makefile that came with AFNI, then
00048         make plugout_tt
00049     Otherwise
00050         cc -o plugout_tt -O plugout_tt.c thd_iochan.c -I.
00051 
00052   "thd_iochan.c" contains the routines that do the TCP/IP
00053   socket and IPC shared memory stuff.
00054 ****************************************************************/
00055 
00056 /***** Header file for communication routines *****/
00057 
00058 #include "thd_iochan.h"
00059 
00060 /***** Global variable determining on which system AFNI runs.  *****/
00061 /***** [default is the current system, can be changed by user] *****/
00062 
00063 static char afni_host[128] = "." ;
00064 static char afni_name[128] = "\0" ;
00065 static int  afni_port      = 8001 ;
00066 
00067 static int  afni_verbose = 0 ;  /* print out debug info? */
00068 static int  afni_do_ijk  = 0 ;  /* do IJK instead of TT? */
00069 
00070 /***** Prototype *****/
00071 
00072 int afni_io(void) ;
00073 
00074 /*===================================================================
00075    Main program:
00076      Read command line for options
00077      Call afni_io routine forever
00078 =====================================================================*/
00079 
00080 int main( int argc , char * argv[] )
00081 {
00082    int narg , ii ;
00083 
00084    /***** See if the pitiful user wants help *****/
00085 
00086    if( argc == 2 && strncmp(argv[1],"-help",5) == 0 ){
00087       printf("Usage: plugout_tt [-host name] [-v]\n"
00088              "This program connects to AFNI and receives notification\n"
00089              "whenever the user changes Talairach coordinates.\n\n"
00090              "Options:\n"
00091              "  -host name  Means to connect to AFNI running on the\n"
00092              "                computer 'name' using TCP/IP.  The default is to\n"
00093              "                connect on the current host using shared memory.\n"
00094              "  -ijk        Means to get voxel indices from AFNI, rather\n"
00095              "                than Talairach coordinates.\n"
00096              "  -v          Verbose mode: prints out lots of stuff.\n"
00097              "  -port pp    Use TCP/IP port number 'pp'.  The default is\n"
00098              "                8001, but if two copies of this are running on\n"
00099              "                the same computer, they must use different ports.\n"
00100              "  -name sss   Use the string 'sss' for the name that AFNI assigns\n"
00101              "                to this plugout.  The default is something stupid.\n"
00102             ) ;
00103       exit(0) ;
00104    }
00105 
00106    /***** Process command line options *****/
00107 
00108    narg = 1 ;
00109    while( narg < argc ){
00110 
00111       /** -host name **/
00112 
00113       if( strncmp(argv[narg],"-host",5) == 0 ){
00114          narg++ ;
00115          if( narg >= argc ){
00116             fprintf(stderr,"-host needs a following name!\a\n"); exit(1);
00117          }
00118          strcpy( afni_host , argv[narg] ) ;
00119          narg++ ; continue ;
00120       }
00121 
00122       /** -name sss **/
00123 
00124       if( strncmp(argv[narg],"-name",5) == 0 ){
00125          narg++ ;
00126          if( narg >= argc ){
00127             fprintf(stderr,"-name needs a following string!\a\n"); exit(1);
00128          }
00129          strcpy( afni_name , argv[narg] ) ;
00130          narg++ ; continue ;
00131       }
00132 
00133       /** -v **/
00134 
00135       if( strncmp(argv[narg],"-v",2) == 0 ){
00136          afni_verbose = 1 ;
00137          narg++ ; continue ;
00138       }
00139 
00140       /** -port pp **/
00141 
00142       if( strncmp(argv[narg],"-port",4) == 0 ){
00143          narg++ ;
00144          if( narg >= argc ){
00145             fprintf(stderr,"-port needs a following argument!\a\n"); exit(1);
00146          }
00147          afni_port = strtol( argv[narg] , NULL , 10 ) ;
00148          if( afni_port <= 0 ){
00149             fprintf(stderr,"-port needs a positive argument!\a\n"); exit(1);
00150          }
00151          if( strcmp(afni_host,".") == 0 ) strcpy(afni_host,"localhost") ;
00152          narg++ ; continue ;
00153       }
00154 
00155       /** -ijk **/
00156 
00157       if( strncmp(argv[narg],"-ijk",4) == 0 ){
00158          afni_do_ijk = 1 ;
00159          narg++ ; continue ;
00160       }
00161 
00162       /** Je ne sais pas **/
00163 
00164       fprintf(stderr,"Unrecognized option: %s\a\n",argv[narg]) ;
00165       exit(1) ;
00166    }
00167 
00168    /***** Loop and check in with AFNI every 100 msec *****/
00169 
00170    while( 1 ){
00171       ii = afni_io() ;        /* commune with AFNI  */
00172       if( ii < 0 ) exit(0) ;  /* bad trip? then die */
00173       iochan_sleep(100) ;     /* perchance to dream */
00174    }
00175 
00176 }
00177 
00178 /*===================================================================
00179   This routine handles all communications with AFNI.
00180   The only input is the global variable afni_host, which determines
00181   on which system AFNI is running.
00182   The output is -1 if an error occured, 0 if everything is OK.
00183 =====================================================================*/
00184 
00185 /***** Mode flags for determining what afni_io does.
00186        The routine progress through 5 stages:
00187 
00188        1) Open a control connection to AFNI;
00189      then
00190        2) Wait until AFNI also opens the control connection;
00191      then
00192        3) Send a control string to AFNI saying what kind of
00193             information we want, wait for an acknowledgment,
00194             close the control connection, and open a data
00195             connection to AFNI;
00196      then
00197        4) Wait for AFNI to also open the data connection;
00198      then
00199        5) See if AFNI sends any data, and if so, process it!  *****/
00200 
00201 #define AFNI_OPEN_CONTROL_MODE  1  /* 1st time thru: open control channel */
00202 #define AFNI_WAIT_CONTROL_MODE  2  /* wait for AFNI to open control chan  */
00203 #define AFNI_OPEN_DATA_MODE     3  /* now can open data channel to AFNI   */
00204 #define AFNI_WAIT_DATA_MODE     4  /* waiting for AFNI to open data chan  */
00205 #define AFNI_CONTINUE_MODE      5  /* at last! data channel is ready!     */
00206 
00207 /***** macros to send acknowledgement strings to AFNI *****/
00208 
00209 #define POACKSIZE       4  /* length of acknowledgement strings */
00210 
00211 #define PO_ACK_BAD(ic)  iochan_sendall( (ic) , "BAD" , POACKSIZE )
00212 #define PO_ACK_OK(ic)   iochan_sendall( (ic) , "OK!" , POACKSIZE )
00213 #define PO_SEND(ic,str) iochan_sendall( (ic) , (str) , strlen((str))+1 )
00214 
00215 int afni_io(void)
00216 {
00217    static int afni_mode = AFNI_OPEN_CONTROL_MODE ;  /* status variable */
00218    static IOCHAN * afni_ioc = NULL ;                /* connection to AFNI */
00219    int ii ;
00220 
00221    /***************************************************************/
00222    /***** Check to see if status is OK before we proceed.     *****/
00223    /***** (if an error occurs below, afni_mode gets set to 0) *****/
00224 
00225    if( afni_mode <= 0 ) return -1 ;
00226 
00227    /***********************************************************************/
00228    /***** First time into this routine?  Open control channel to AFNI *****/
00229 
00230    if( afni_mode == AFNI_OPEN_CONTROL_MODE ){
00231       char afni_iocname[128] ;           /* will hold name of I/O channel */
00232 
00233       /** Note that the control channel is always a
00234           TCP/IP channel to port # 7955 on the AFNI host system **/
00235 
00236       if( strcmp(afni_host,".") == 0 )
00237          sprintf( afni_iocname , "tcp:%s:7955" , "localhost" ); /* make name */
00238       else
00239          sprintf( afni_iocname , "tcp:%s:7955" , afni_host ) ;  /* make name */
00240       afni_ioc = iochan_init( afni_iocname , "create" ) ;    /* create it */
00241       if( afni_ioc == NULL ){
00242          fprintf(stderr,
00243                  "Can't create control channel %s to AFNI!\n",afni_iocname) ;
00244          afni_mode = 0 ;
00245          return -1 ;
00246       }
00247       afni_mode = AFNI_WAIT_CONTROL_MODE ; /* waiting for AFNI connection */
00248       if( afni_verbose )
00249          fprintf(stderr,"AFNI control channel created\n") ;
00250    }
00251 
00252    /****************************************************/
00253    /**** Check if AFNI control channel is connected ****/
00254 
00255    if( afni_mode == AFNI_WAIT_CONTROL_MODE ){
00256       ii = iochan_writecheck( afni_ioc , 5 ) ;     /* wait at most 5 msec */
00257 
00258       /** the iochan_*check() routines return
00259              -1 for an error,
00260               0 if not ready,
00261              >0 if the I/O channel is ready. **/
00262 
00263       if( ii < 0 ){
00264          fprintf(stderr,"Control channel to AFNI failed!\a\n") ;
00265          IOCHAN_CLOSE(afni_ioc) ;
00266          afni_mode = 0 ;
00267          return -1 ;
00268       } else if( ii > 0 ){
00269          afni_mode = AFNI_OPEN_DATA_MODE ;        /* prepare to send data */
00270          if( afni_verbose )
00271             fprintf(stderr,"AFNI control channel connected\n");
00272       } else {
00273          return 0 ;                                /* try again next time */
00274       }
00275    }
00276 
00277    /**********************************************************/
00278    /**** Send control data to AFNI, and open data channel ****/
00279 
00280    if( afni_mode == AFNI_OPEN_DATA_MODE ){
00281       char afni_iocname[128] ;
00282       char afni_buf[256] ;
00283 
00284       /** decide name of data channel:
00285             use shared memory (shm:) on ".",
00286             use TCP/IP (tcp:) on other computer systems;
00287         * Note that the TCP/IP port number can be
00288            anything that isn't already in use;
00289         * Note that the shm control name (here "test_plugout")
00290            is a string that will be converted to an IPC
00291            key (in function string_to_key in iochan.c).       **/
00292 
00293       if( strcmp(afni_host,".") == 0 )
00294          strcpy( afni_iocname , "shm:test_plugout:1K+1K" ) ;
00295       else
00296          sprintf( afni_iocname , "tcp:%s:%d" , afni_host , afni_port ) ;
00297 
00298       /** write the command to AFNI into the buffer:
00299             * each command ends with a newline character,
00300                 except (possibly) the last command;
00301             * the command buffer is a C string, which ends
00302                 with an ASCII NUL character;
00303             * TT_XYZ_DELTA means 'send me T-T coordinates when they change';
00304             * DSET_IJK_DELTA means 'send me IJK voxel indices when they change';
00305             * PONAME means 'use this string for informative messages';
00306             * IOCHAN means 'use this I/O channel from now on'. **/
00307 
00308       if( afni_name[0] == '\0' ) strcpy(afni_name,"aManCalledHorse") ;
00309 
00310       if( afni_do_ijk ){
00311          sprintf( afni_buf , "DSET_IJK_DELTA\n"
00312                              "UNDERLAY_DELTA\n"
00313                              "PONAME %s\n"
00314                              "IOCHAN %s" ,
00315                   afni_name , afni_iocname ) ;
00316       } else {
00317          sprintf( afni_buf , "TT_XYZ_DELTA\n"
00318                              "UNDERLAY_DELTA\n"
00319                              "PONAME %s\n"
00320                              "IOCHAN %s" ,
00321                   afni_name , afni_iocname ) ;
00322       }
00323 
00324       if( afni_verbose )
00325          fprintf(stderr,"Sending control information to AFNI\n") ;
00326 
00327       /** note that the ASCII NUL at the end of the buffer is sent **/
00328 
00329       ii = iochan_sendall( afni_ioc , afni_buf , strlen(afni_buf)+1 ) ;
00330 
00331       /** the return value is the number of bytes sent,
00332           or -1 indicating a fatal error transpired.    **/
00333 
00334       if( ii < 0 ){
00335          fprintf(stderr,"Transmission of control data to AFNI failed!\a\n") ;
00336          IOCHAN_CLOSE(afni_ioc) ;
00337          afni_mode = 0 ;
00338          return -1 ;
00339 
00340       } else {
00341 
00342          /** wait for the acknowledgment from AFNI, then close channel **/
00343 
00344          ii = iochan_recvall( afni_ioc , afni_buf , POACKSIZE ) ;
00345          IOCHAN_CLOSE(afni_ioc) ;
00346 
00347          if( ii < 0 || strncmp(afni_buf,"OK!",3) != 0 ){
00348             fprintf(stderr,"AFNI didn't like control information!\a\n") ;
00349             afni_mode = 0 ;
00350             return -1 ;
00351          }
00352 
00353          /** now open data channel to AFNI **/
00354 
00355          afni_ioc = iochan_init( afni_iocname , "create" ) ;
00356          if( afni_ioc == NULL ){
00357             fprintf(stderr,
00358                     "Can't open data channel %s to AFNI!\a\n",afni_iocname) ;
00359             afni_mode = 0 ;
00360             return -1 ;
00361          } else {
00362             afni_mode = AFNI_WAIT_DATA_MODE ;
00363             if( afni_verbose ) fprintf(stderr,"AFNI data channel created\n") ;
00364          }
00365       }
00366    }
00367 
00368    /****************************************************/
00369    /***** See if data channel is connected to AFNI *****/
00370 
00371    if( afni_mode == AFNI_WAIT_DATA_MODE ){
00372 
00373       ii = iochan_goodcheck( afni_ioc , 5 ) ;  /* wait at most 5 msec */
00374       if( ii < 0 ){
00375          fprintf(stderr,
00376                  "AFNI data channel aborted before any data was sent!\a\n") ;
00377          IOCHAN_CLOSE( afni_ioc ) ;
00378          afni_mode = 0 ;
00379          return -1 ;
00380       } else if( ii > 0 ){                     /* ready to go! */
00381          afni_mode = AFNI_CONTINUE_MODE ;
00382          if( afni_verbose ) fprintf(stderr,"AFNI data channel is open\n") ;
00383       } else {
00384          return 0 ;                            /* try again next time */
00385       }
00386    }
00387 
00388    /************************************************************/
00389    /***** The "normal" state of affairs:                   *****/
00390    /***** AFNI is connected.  See if any data is arriving. *****/
00391 
00392    if( afni_mode == AFNI_CONTINUE_MODE ){
00393       char afni_buf[256] ;
00394       float xx , yy , zz ;
00395       int   ix , jy , kz ;
00396 
00397       ii = iochan_readcheck( afni_ioc , 0 ) ;  /* don't wait */
00398 
00399       /** ii <  0  ==>  a fatal error has happened
00400           ii == 0  ==>  no data is ready
00401           ii >  0  ==>  data is ready to read from the channel **/
00402 
00403       if( ii < 0 ){
00404          fprintf(stderr,"AFNI data channel aborted!\a\n") ;
00405          IOCHAN_CLOSE(afni_ioc) ;
00406          afni_mode = 0 ;
00407          return -1 ;
00408       } else if( ii == 0 ){
00409          return 0 ;       /* no data ==> try again next time */
00410       }
00411 
00412       /** at this point, data is incoming from AFNI **/
00413 
00414       ii = iochan_recv( afni_ioc , afni_buf , 256 ) ;
00415 
00416       if( ii <= 0 ){
00417          fprintf(stderr,"AFNI data channel recv failed!\a\n") ;
00418          IOCHAN_CLOSE(afni_ioc) ;
00419          afni_mode = 0 ;
00420          return -1 ;
00421       }
00422 
00423       /** at last! "process" the data from AFNI
00424                    (in this case, just print it out) **/
00425 
00426 #if 0
00427       if( afni_do_ijk )
00428          ii = sscanf( afni_buf , "DSET_IJK %d %d %d" , &ix,&jy,&kz ) ;
00429       else
00430          ii = sscanf( afni_buf , "TT_XYZ %f %f %f"   , &xx,&yy,&zz ) ;
00431 
00432       /** also, AFNI will wait until we send an acknowledgment;
00433           acknowledgment messages are always 4 (POACKSIZE) bytes long **/
00434 
00435       if( ii < 3 ){
00436          fprintf(stderr,"AFNI sent bad data: %s\a\n",afni_buf) ;
00437          PO_ACK_BAD(afni_ioc) ;
00438       } else if( afni_do_ijk ){
00439          fprintf(stderr,"AFNI sent indices: %d %d %d\n",ix,jy,kz) ;
00440          PO_ACK_OK(afni_ioc) ;
00441       } else {
00442          fprintf(stderr,"AFNI sent coords: %9.3f %9.3f %9.3f\n",xx,yy,zz) ;
00443          PO_ACK_OK(afni_ioc) ;
00444       }
00445 #else
00446       fprintf(stderr,"AFNI sent data:\n%s\n",afni_buf) ;
00447       PO_ACK_OK(afni_ioc) ;
00448 #endif
00449    }
00450 
00451    return 0 ;
00452 }
 

Powered by Plone

This site conforms to the following standards: