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