1 /*****************************************************************************
2 Major portions of this software are copyrighted by the Medical College
3 of Wisconsin, 1994-2000, and are released under the Gnu General Public
4 License, Version 2. See the file README.Copyright for details.
5 ******************************************************************************/
6
7 #include "mrilib.h"
8
9 #define MAX_CHAN 32 /* 02 Aug 2002: cf. plug_realtime.c */
10
11 static THD_3dim_dataset * RT_dset[MAX_CHAN] ;
12 static float RT_dt = 0.0 ;
13 static int RT_3D = 0 ;
14 static int RT_swap2 = 0 ;
15 static char RT_buf[32768] , RT_com[1024] ;
16 static int RT_mega = 1 ;
17
18 /*=============================================================================*/
19
20 #if 0 /* ZSS June 2011. Delete useless code after dust has settled. */
21 #define AFNI_CONTROL_PORT 7954 /* always send control data to AFNI */
22 #define AFNI_TCP_PORT 7953 /* maybe send image data to AFNI */
23 /*
24 replace these two with:
25 get_port_named("AFNI_CONTROL_PORT")
26 and
27 get_port_named("AFNI_TCP_PORT")
28 */
29 #endif
30
31 #define AFNI_OPEN_CONTROL_MODE 1 /* 1st time thru: open control channel */
32 #define AFNI_WAIT_CONTROL_MODE 2 /* waiting for AFNI to open control */
33 #define AFNI_OPEN_DATA_MODE 3 /* now can open data channel to AFNI */
34 #define AFNI_CATCHUP_MODE 4 /* waiting for AFNI to open data */
35 #define AFNI_CONTINUE_MODE 5 /* at last! data channel is ready! */
36
37 /*-- global control variables --*/
38
39 int AFNI_mode = 0 ; /* if > 0, then means AFNI is active */
40 int AFNI_use_tcp = 0 ; /* if > 0, use TCP/IP to send images */
41 char AFNI_host[128] = "localhost" ; /* hostname of CPU AFNI is on */
42 char AFNI_iochan[128] = "\0" ; /* I/O channel name to AFNI */
43 IOCHAN * AFNI_ioc = NULL ; /* ptr to I/O channel itself */
44 char AFNI_buf[1024] ; /* temporary space */
45 int AFNI_verbose = 0 ; /* debugging mode */
46
47 char AFNI_infocom[256]= "\0" ; /* command for AFNI info */
48
49 /*-- prototypes --*/
50
51 void RT_start_io(void) ;
52 void RT_exit(void) ;
53
54 /*-- how to execute a command on another system --*/
55
56 #ifdef HP
57 # define RSH "remsh"
58 #else
59 # define RSH "rsh"
60 #endif
61
62 /*=============================================================================*/
63
RT_exit(void)64 void RT_exit(void) /* Function to be called to make sure */
65 { /* the AFNI data channels get closed. */
66 fprintf(stderr,"*** RT_exit: closing data channel to AFNI\n") ;
67 iochan_close(AFNI_ioc) ;
68 return ;
69 }
70
71 /*-----------------------------------------------------------------------------*/
72
73 #include <signal.h>
74
RT_sigfunc(int sig)75 void RT_sigfunc(int sig) /** signal handler for fatal errors **/
76 {
77 char * sname ;
78 static volatile int fff=0 ;
79 if( fff ) _exit(1) ; else fff = 1 ;
80 switch(sig){
81 default: sname = "unknown" ; break ;
82 case SIGINT: sname = "SIGINT" ; break ;
83 case SIGPIPE: sname = "SIGPIPE" ; break ;
84 case SIGSEGV: sname = "SIGSEGV" ; break ;
85 case SIGBUS: sname = "SIGBUS" ; break ;
86 case SIGTERM: sname = "SIGTERM" ; break ;
87 }
88 fprintf(stderr,"\n*** Fatal Signal %d (%s) received\n",sig,sname) ;
89 exit(1) ;
90 }
91
92 /*****************************************************************************
93 Do I/O startup stuff.
94
95 At any given moment, this routine is in one of a number of modes
96 (the AFNI_mode variable).
97 The first time in, AFNI_mode == AFNI_OPEN_CONTROL_MODE. In each mode,
98 certain tasks must be accomplished and this program must be synchronized
99 with AFNI. When the necessary deeds are done, the routine advances to
100 the next mode. If the deeds cannot be done when this routine is called,
101 then it will stay in the same mode, and the next time it is called it
102 will try to do them again. This routine should be called repeatedly
103 until it progresses to the last mode (AFNI_CONTINUE_MODE), which is for
104 normal transmission of images (one at a time) to AFNI.
105
106 If an error occurs, so that this program can no longer talk to AFNI, then
107 AFNI_mode is set to 0, which means "do nothing further". The rest of
108 the data acquisition software will continue, but these routines will
109 be stopped dead.
110 ******************************************************************************/
111
AFNI_start_io(void)112 void AFNI_start_io( void )
113 {
114 int ii , jj ;
115
116 /***** Check for conditions in which to do nothing *****/
117
118 if( AFNI_mode <= 0 || AFNI_mode == AFNI_CONTINUE_MODE ) return ;
119
120 /***** If we are at the first time in,
121 try to open a control socket to talk to AFNI *****/
122
123 if( AFNI_mode == AFNI_OPEN_CONTROL_MODE ){
124
125 sprintf( AFNI_iochan , "tcp:%s:%d" ,
126 AFNI_host , get_port_named("AFNI_CONTROL_PORT") ) ;
127
128 if( AFNI_verbose )
129 fprintf(stderr,"Opening control channel %s to AFNI.\n",AFNI_iochan) ;
130
131 AFNI_ioc = iochan_init( AFNI_iochan , "w" ) ;
132
133 if( AFNI_ioc == NULL ){
134 fprintf(stderr,"Can't open control channel %s to AFNI!\a\n",AFNI_iochan) ;
135 #if 0
136 AFNI_mode = 0 ; /* disable AFNI */
137 #endif
138 return ;
139 } else {
140 if( AFNI_verbose ) fprintf(stderr,"Entering AFNI_WAIT_CONTROL_MODE.\n") ;
141 AFNI_mode = AFNI_WAIT_CONTROL_MODE ; /* begin waiting for AFNI connection */
142 iochan_sleep(5) ; /* give other program a moment */
143 }
144 }
145
146 /***** Check if the control socket is connected to AFNI *****/
147
148 if( AFNI_mode == AFNI_WAIT_CONTROL_MODE ){
149
150 ii = iochan_writecheck( AFNI_ioc , 1 ) ; /* Check; wait at most 1 msec */
151
152 /** if ii == 0, then the channel is still pending,
153 so do nothing; otherwise, take some action. **/
154
155 if( ii < 0 ){
156 fprintf(stderr,"Control channel to AFNI failed!\a\n") ;
157 IOCHAN_CLOSE(AFNI_ioc) ;
158 AFNI_mode = 0 ; /* disable AFNI */
159 return ;
160 } else if( ii > 0 ){
161 if( AFNI_verbose ) fprintf(stderr,"Control channel connected to AFNI."
162 " Entering AFNI_OPEN_DATA_MODE.\n") ;
163 AFNI_mode = AFNI_OPEN_DATA_MODE ; /* prepare to send data to AFNI */
164 }
165 }
166
167 /***** Send the control information, which says
168 how we will talk to AFNI in the future (shmem or TCP/IP),
169 then close the control channel and open this new data channel *****/
170
171 if( AFNI_mode == AFNI_OPEN_DATA_MODE ){
172
173 /* decide name of data channel: it can be TCP/IP or shared memory */
174
175 if( AFNI_use_tcp ) sprintf(AFNI_iochan,"tcp:%s:%d",
176 AFNI_host,get_port_named("AFNI_TCP_PORT")) ;
177 else if( RT_mega ) sprintf(AFNI_iochan,"shm:grv:%dM",RT_mega) ;
178 else sprintf(AFNI_iochan,"shm:grv:50K") ; /* 11 Dec 2002 */
179
180 strcpy(AFNI_buf,AFNI_iochan) ; /* tell AFNI where to read data */
181 if( AFNI_infocom[0] != '\0' ){
182 strcat(AFNI_buf,"\n") ;
183 strcat(AFNI_buf,AFNI_infocom) ; /* tell it where to get 3T info */
184 }
185
186 if( AFNI_verbose )
187 fprintf(stderr,"Sending control information to AFNI:\n%s\n",AFNI_buf) ;
188
189 ii = iochan_sendall( AFNI_ioc , AFNI_buf , strlen(AFNI_buf)+1 ) ;
190
191 /** A negative return is bad news **/
192
193 if( ii < 0 ){
194 fprintf(stderr,"Transmission of control data to AFNI failed!\a\n") ;
195 IOCHAN_CLOSE(AFNI_ioc) ;
196 AFNI_mode = 0 ;
197 return ;
198 } else {
199 while( ! iochan_clearcheck(AFNI_ioc,2) ) /* wait for control data to clear */
200 iochan_sleep(2) ;
201 IOCHAN_CLOSE(AFNI_ioc) ; /* close control channel */
202
203 if( AFNI_verbose )
204 fprintf(stderr,"Opening data channel %s to AFNI.\n",AFNI_iochan) ;
205
206 AFNI_ioc = iochan_init( AFNI_iochan , "w" ) ; /* open data channel */
207 if( AFNI_ioc == NULL ){
208 fprintf(stderr,"Can't open data channel %s to AFNI!\a\n",AFNI_iochan) ;
209 AFNI_mode = 0 ;
210 return ;
211 } else {
212 if( AFNI_verbose ) fprintf(stderr,"Entering AFNI_CATCHUP_MODE.\n") ;
213 AFNI_mode = AFNI_CATCHUP_MODE ;
214 iochan_sleep(5) ; /* give other program a moment */
215 }
216 }
217 }
218
219 /***** Wait for the data channel to be connected to AFNI,
220 and then send any images that are reconstructed and ready to go *****/
221
222 if( AFNI_mode == AFNI_CATCHUP_MODE ){
223
224 ii = iochan_writecheck( AFNI_ioc , 1 ) ; /* wait at most 1 msec */
225 if( ii < 0 ){
226 fprintf(stderr,"AFNI data channel aborted before any data was sent!\a\n") ;
227 IOCHAN_CLOSE( AFNI_ioc ) ;
228 AFNI_mode = 0 ;
229 return ;
230 } else if( ii > 0 ){ /* can now send data to AFNI! */
231 if( AFNI_verbose )
232 fprintf(stderr,"AFNI data channel %s is connected.\n"
233 "Entering AFNI_CONTINUE_MODE.\n" , AFNI_iochan) ;
234 AFNI_mode = AFNI_CONTINUE_MODE ;
235 }
236 }
237
238 return ;
239 }
240
241 /*****************************************************************************/
242
243 /* 11 Dec 2002: string to mark end of image data,
244 to enable ending dataset(s) without closing data channel */
245
246 #define COMMAND_MARKER "Et Earello Endorenna utulien!!"
247 #define COMMAND_MARKER_LENGTH 30
248
main(int argc,char * argv[])249 int main( int argc , char * argv[] )
250 {
251 int iarg=1 , ii,tt,kk , nbytes , nbslice , ntran , nzfake=0 ;
252 char *bar , *qar=NULL , *sar ;
253 double start_time=0.0 , left_time , xtime ;
254 char *drive_afni[128] ;
255 int ndrive=0 ;
256 int num_chan , cur_chan , cc ;
257 char *note[128] ; /* 02 Oct 2002 */
258 int num_note=0 ;
259 int num_start=0 , jarg , bwait ; /* 11 Dec 2002 */
260 float gyr=0.0 ; /* 29 Jan 2004 */
261
262 /*-- help the ignorant user --*/
263
264 if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
265 printf(
266 "Usage: rtfeedme [options] dataset [dataset ...]\n"
267 "Test the real-time plugin by sending all the bricks in 'dataset' to AFNI.\n"
268 " * 'dataset' may include a sub-brick selector list.\n"
269 " * If more than one dataset is given, multiple channel acquisition\n"
270 " will be simulated. Each dataset must then have the same datum\n"
271 " and dimensions.\n"
272 " * If you put the flag '-break' between datasets, then the datasets\n"
273 " in each group will be transmitted in parallel, but the groups\n"
274 " will be transmitted serially (one group, then another, etc.).\n"
275 " + For example:\n"
276 " rtfeedme A+orig B+orig -break C+orig -break D+orig\n"
277 " will send the A and B datasets in parallel, then send\n"
278 " the C dataset separately, then send the D dataset separately.\n"
279 " (That is, there will be 3 groups of datasets.)\n"
280 " + There is a 1 second delay between the end transmission for\n"
281 " a group and the start transmission for the next group.\n"
282 " + You can extend the inter-group delay by using a break option\n"
283 " of the form '-break_20' to indicate a 20 second delay.\n"
284 " + Within a group, each dataset must have the same datum and\n"
285 " same x,y,z,t dimensions. (Different groups don't need to\n"
286 " be conformant to each other.)\n"
287 " + All the options below apply to each group of datasets;\n"
288 " i.e., they will all get the same notes, drive commands, ....\n"
289 "\n"
290 "Options:\n"
291 " -host sname = Send data, via TCP/IP, to AFNI running on the\n"
292 " computer system 'sname'. By default, uses the\n"
293 " current system, and transfers data using shared\n"
294 " memory. To send on the current system using\n"
295 " TCP/IP, use the system 'localhost'.\n"
296 "\n"
297 " -dt ms = Tries to maintain an inter-transmit interval of\n"
298 " 'ms' milliseconds. The default is to send data\n"
299 " as fast as possible.\n"
300 "\n"
301 " -3D = Sends data in 3D bricks. By default, sends in\n"
302 " 2D slices.\n"
303 "\n"
304 " -buf m = When using shared memory, sets the interprocess\n"
305 " communications buffer to 'm' megabytes. Has no\n"
306 " effect if using TCP/IP. Default is m=1.\n"
307 " If you use m=0, then a 50 Kbyte buffer is used.\n"
308 "\n"
309 " -verbose = Be talkative about actions.\n"
310 " -swap2 = Swap byte pairs before sending data.\n"
311 "\n"
312 " -nzfake nz = Send 'nz' as the value of nzz (for debugging).\n"
313 "\n"
314 " -drive cmd = Send 'cmd' as a DRIVE_AFNI command; e.g.,\n"
315 " -drive 'OPEN_WINDOW A.axialimage'\n"
316 " If cmd contains blanks, it must be in 'quotes'.\n"
317 " Multiple -drive options may be used.\n"
318 "\n"
319 " -note sss = Send 'sss' as a NOTE to the realtime plugin.\n"
320 " Multiple -note options may be used.\n"
321 "\n"
322 " -gyr v = Send value 'v' as the y-range for realtime motion\n"
323 " estimation graphing.\n"
324 ) ;
325 exit(0) ;
326 }
327
328 mainENTRY("rtfeedme") ;
329
330 /*-- scan arguments --*/
331
332 while( iarg < argc && argv[iarg][0] == '-' ){
333
334 if( strcmp(argv[iarg],"-gyr") == 0 ){ /* 29 Jan 2004 */
335 gyr = strtod( argv[++iarg] , NULL ) ;
336 iarg++ ; continue ;
337 }
338
339 if( strcmp(argv[iarg],"-drive") == 0 ){ /* 30 Jul 2002 */
340 drive_afni[ndrive++] = argv[++iarg] ;
341 iarg++ ; continue ;
342 }
343
344 if( strcmp(argv[iarg],"-note") == 0 ){ /* 02 Oct 2002 */
345 note[num_note++] = argv[++iarg] ;
346 iarg++ ; continue ;
347 }
348
349 if( strcmp(argv[iarg],"-nzfake") == 0 ){
350 nzfake = (int) strtod( argv[++iarg] , NULL ) ;
351 iarg++ ; continue ;
352 }
353
354 if( strcmp(argv[iarg],"-buf") == 0 ){
355 RT_mega = (int) strtod( argv[++iarg] , NULL ) ;
356 if( RT_mega < 0 ){
357 fprintf(stderr,"*** Illegal value after -buf\n") ; exit(1) ;
358 }
359 iarg++ ; continue ;
360 }
361
362 if( strcmp(argv[iarg],"-host") == 0 ){
363 strcpy( AFNI_host , argv[++iarg] ) ;
364 AFNI_use_tcp = 1 ;
365 iarg++ ; continue ;
366 }
367
368 if( strcmp(argv[iarg],"-dt") == 0 ){
369 RT_dt = strtod( argv[++iarg] , NULL ) * 0.001 ;
370 iarg++ ; continue ;
371 }
372
373 if( strcmp(argv[iarg],"-3D") == 0 ){
374 RT_3D = 1 ;
375 iarg++ ; continue ;
376 }
377
378 if( strcmp(argv[iarg],"-swap2") == 0 ){
379 RT_swap2 = 1 ;
380 iarg++ ; continue ;
381 }
382
383 if( strcmp(argv[iarg],"-verbose") == 0 ){
384 AFNI_verbose = 1 ;
385 iarg++ ; continue ;
386 }
387
388 fprintf(stderr,"*** Unrecognized option: %s\n",argv[iarg]) ;
389 exit(1) ;
390 }
391
392 /*-- this stuff is one-time-only setup of the I/O to AFNI --*/
393
394 atexit(RT_exit) ; /* call this when program ends */
395 AFNI_mode = AFNI_OPEN_CONTROL_MODE ; /* mode in which to start I/O */
396
397 signal(SIGINT ,RT_sigfunc) ; /* setup signal handler */
398 signal(SIGBUS ,RT_sigfunc) ; /* for fatal errors */
399 signal(SIGSEGV,RT_sigfunc) ;
400 signal(SIGTERM,RT_sigfunc) ;
401
402 /*------ 11 Dec 2002: after a -break, will jump back here ------*/
403
404 Restart:
405
406 /*-- count datasets up to end of argv or next -break --*/
407
408 jarg = iarg ; /* keep track of where we are starting */
409 num_chan = 0 ;
410 for( ; iarg < argc && strncmp(argv[iarg],"-break",6) != 0 ; iarg++ ) num_chan++;
411 if( num_chan == 0 ){
412 fprintf(stderr,"*** No more datasets! Free, free, free at last!\n"); exit(0);
413 }
414 if( num_chan > MAX_CHAN ){
415 fprintf(stderr,"*** Too many datasets on command line!\n"); exit(1);
416 }
417
418 /*-- skip any -break's for when we loop back to Restart --*/
419
420 for( ; iarg < argc && strncmp(argv[iarg],"-break",6) == 0 ; iarg++ ) ; /* nada */
421
422 /* check for delay in the form of "-break_XXX" where XXX = # sec to wait */
423
424 bwait = 1 ;
425 if( iarg < argc && strncmp(argv[iarg-1],"-break_",7) == 0 ){
426 bwait = strtol( argv[iarg-1]+7 , NULL , 10 ) ;
427 }
428 if( bwait < 0 ) bwait = 1 ;
429
430 num_start++ ; /* number of times we've been here */
431
432 /*-- read the input dataset(s) and check them for OK-ositiness --*/
433
434 for( cc=0 ; cc < num_chan ; cc++ ){
435
436 RT_dset[cc] = THD_open_dataset( argv[jarg+cc] ) ;
437
438 if( RT_dset[cc] == NULL ){
439 fprintf(stderr,"*** Can't open dataset %s\n",argv[jarg+cc]); exit(1);
440 }
441
442 if( cc > 0 ){ /* check for compatibility with #0 */
443
444 #define ERREX(ee) \
445 do { fprintf(stderr,"*** " ee ":%s and %s\n",argv[jarg],argv[jarg+cc]) ; \
446 exit(1) ; } while(0)
447
448 if( DSET_NX (RT_dset[0]) != DSET_NX (RT_dset[cc]) ) ERREX("nx mismatch") ;
449 if( DSET_NY (RT_dset[0]) != DSET_NY (RT_dset[cc]) ) ERREX("ny mismatch") ;
450 if( DSET_NZ (RT_dset[0]) != DSET_NZ (RT_dset[cc]) ) ERREX("nz mismatch") ;
451
452 if( DSET_NVALS(RT_dset[0]) != DSET_NVALS(RT_dset[cc]) ) ERREX("nvals mismatch");
453
454 if( DSET_BRICK_TYPE(RT_dset[0],0) != DSET_BRICK_TYPE(RT_dset[cc],0) )
455 ERREX("datum mismatch");
456 }
457
458 /* load from disk */
459
460 DSET_load(RT_dset[cc]) ;
461 if( !DSET_LOADED(RT_dset[cc]) ){
462 fprintf(stderr,"*** Can't load dataset %s\n",argv[jarg+cc]); exit(1);
463 }
464 } /* end of loop over channels (datasets to send in parallel) */
465
466 /*-- initiate communications with AFNI --*/
467
468 if( AFNI_verbose ) fprintf(stderr,"--- Starting I/O to AFNI\n") ;
469
470 AFNI_start_io() ;
471
472 ii = 1 ;
473 while( AFNI_mode > 0 && AFNI_mode != AFNI_CONTINUE_MODE && ii < 1000 ){
474 iochan_sleep( 300 ) ; /* 300 msec wait */
475 AFNI_start_io() ;
476 ii++ ;
477 }
478
479 if( AFNI_mode != AFNI_CONTINUE_MODE ){
480 fprintf(stderr,"\n*** Can't connect to AFNI?!\n") ; exit(1) ;
481 }
482
483 if( AFNI_verbose )
484 fprintf(stderr,"\n--- Connection to AFNI is ready after %d tries\n",ii) ;
485
486 /*-- Send dataset control information --*/
487
488 #define ADDTO_BUF ( strcat(RT_buf,RT_com) , strcat(RT_buf,"\n") )
489
490 RT_buf[0] = '\0' ; /* string to hold commands to AFNI realtime plugin */
491
492 /*** Number of channels [Aug 2002] ***/
493
494 if( num_chan > 1 ){ /* default is 1 channel */
495 sprintf(RT_com,"NUM_CHAN %d",num_chan) ;
496 ADDTO_BUF ;
497 }
498
499 /*** How the data will be sent ***/
500
501 strcpy(RT_com,"ACQUISITION_TYPE ") ;
502 if( DSET_NVALS(RT_dset[0]) == 1 ){
503 if( RT_3D ) strcat(RT_com,"3D") ; /* 1 3D array, all at once */
504 else strcat(RT_com,"2D+z") ; /* 1 3D array, by slices */
505 } else {
506 if( RT_3D ) strcat(RT_com,"3D+t") ; /* multi 3D arrays, each all at once */
507 else strcat(RT_com,"2D+zt") ; /* multi 3D arrays, each by slices */
508 }
509 ADDTO_BUF ;
510
511 /*** Time step, if needed ***/
512
513 if( DSET_NVALS(RT_dset[0]) > 1 && DSET_TR(RT_dset[0]) > 0.0 ){
514 float TR = DSET_TR(RT_dset[0]) ;
515 if( DSET_TIMEUNITS(RT_dset[0]) == UNITS_MSEC_TYPE ) TR *= 0.001 ;
516 sprintf( RT_com , "TR %f" , TR ) ;
517 ADDTO_BUF ;
518 }
519
520 /*** Volume dimensions ***/
521
522 sprintf( RT_com, "XYFOV %f %f %f", fabs(DSET_DX(RT_dset[0]) * DSET_NX(RT_dset[0])) ,
523 fabs(DSET_DY(RT_dset[0]) * DSET_NY(RT_dset[0])) ,
524 fabs(DSET_DZ(RT_dset[0]) * DSET_NZ(RT_dset[0])) ) ;
525 ADDTO_BUF ;
526
527 /*** Matrix sizes ***/
528
529 if( nzfake <= 0 ){
530 sprintf( RT_com , "XYMATRIX %d %d %d" , DSET_NX(RT_dset[0]) ,
531 DSET_NY(RT_dset[0]) ,
532 DSET_NZ(RT_dset[0]) ) ;
533 ADDTO_BUF ;
534 } else {
535 sprintf( RT_com , "XYMATRIX %d %d" , DSET_NX(RT_dset[0]) ,
536 DSET_NY(RT_dset[0]) ) ;
537 ADDTO_BUF ;
538 sprintf( RT_com , "ZNUM %d" , nzfake ) ;
539 ADDTO_BUF ;
540 }
541
542 /*** Data type ***/
543
544 sprintf( RT_com, "DATUM %s", MRI_TYPE_name[DSET_BRICK_TYPE(RT_dset[0],0)] ) ;
545 ADDTO_BUF ;
546
547 /*** Slice order ***/
548
549 if( ! RT_3D ){ /* this cheapo program always */
550 strcpy( RT_com , "ZORDER seq" ) ; /* send slices in sequential order */
551 ADDTO_BUF ; /* unlike their true acquisition */
552 }
553
554 /*** Axes orientation [e.g., RAI] ***/
555
556 sprintf( RT_com , "XYZAXES %s %s %s" ,
557 ORIENT_shortstr[ RT_dset[0]->daxes->xxorient ] ,
558 ORIENT_shortstr[ RT_dset[0]->daxes->yyorient ] ,
559 ORIENT_shortstr[ RT_dset[0]->daxes->zzorient ] ) ;
560 ADDTO_BUF ;
561
562 /*** Axes offsets [11 Dec 2002] ***/
563
564 { float xorg,yorg,zorg ;
565 int xorc,yorc,zorc ;
566
567 xorg = RT_dset[0]->daxes->xxorg ;
568 yorg = RT_dset[0]->daxes->yyorg ;
569 zorg = RT_dset[0]->daxes->zzorg ;
570
571 xorc = RT_dset[0]->daxes->xxorient ;
572 yorc = RT_dset[0]->daxes->yyorient ;
573 zorc = RT_dset[0]->daxes->zzorient ;
574
575 if( ORIENT_sign[xorc] == '+' ) xorc = ORIENT_OPPOSITE(xorc) ;
576 if( ORIENT_sign[yorc] == '+' ) yorc = ORIENT_OPPOSITE(yorc) ;
577 if( ORIENT_sign[zorc] == '+' ) zorc = ORIENT_OPPOSITE(zorc) ;
578
579 sprintf( RT_com , "XYZFIRST %g%c %g%c %g%c" ,
580 xorg , ORIENT_first[xorc] ,
581 yorg , ORIENT_first[yorc] ,
582 zorg , ORIENT_first[zorc] ) ;
583 ADDTO_BUF ;
584 }
585
586 /*** DRIVE_AFNI commands [Jul 2002] ***/
587
588 for( ii=0 ; ii < ndrive ; ii++ ){
589 sprintf( RT_com , "DRIVE_AFNI %s" , drive_afni[ii] ) ;
590 ADDTO_BUF ;
591 }
592
593 /*** NOTE commands [02 Oct 2002] ***/
594
595 for( ii=0 ; ii < num_note ; ii++ ){
596 sprintf( RT_com , "NOTE %s" , note[ii] ) ;
597 ADDTO_BUF ;
598 }
599
600 /*** GRAPH range commands [29 Jan 2004] ***/
601
602 if( DSET_NVALS(RT_dset[0]) > 9 ){
603 sprintf( RT_com , "GRAPH_XRANGE %d" , DSET_NVALS(RT_dset[0]) ) ;
604 ADDTO_BUF ;
605 if( gyr > 0.0 ){
606 sprintf( RT_com , "GRAPH_YRANGE %.2f" , gyr ) ;
607 ADDTO_BUF ;
608 }
609 }
610
611 /*** send metadata buffer to AFNI ***/
612
613 if( AFNI_verbose )
614 fprintf(stderr,"--- Dataset control info for AFNI:\n%s",RT_buf) ;
615
616 ii = iochan_sendall( AFNI_ioc , RT_buf , strlen(RT_buf)+1 ) ;
617 if( ii < 0 ){
618 fprintf(stderr,"*** Error sending dataset control info to AFNI\n") ;
619 exit(1) ;
620 }
621
622 iochan_sleep(128) ; /* let AFNI digest the results for a while */
623
624 /*-- compute number of bytes per slice, and per image transmission --*/
625
626 nbslice = nbytes = mri_datum_size( DSET_BRICK_TYPE(RT_dset[0],0) )
627 * DSET_NX(RT_dset[0]) * DSET_NY(RT_dset[0]) ;
628
629 if( RT_3D ) nbytes *= DSET_NZ(RT_dset[0]) ;
630
631 if( qar != NULL ) free(qar) ; /* free old workspace */
632 qar = (char *) malloc( sizeof(char) * nbytes ) ; /* make new workspace */
633 if( qar == NULL ){
634 fprintf(stderr,"*** Can't malloc workspace!\n"); exit(1);
635 }
636
637 /*--- send slices or volumes to AFNI ---*/
638
639 xtime = COX_clock_time() ; /* keep track of elapsed time */
640
641 ntran = DSET_NVALS(RT_dset[0]) * num_chan ; /* number of transmissions: */
642 if( !RT_3D ) ntran *= DSET_NZ(RT_dset[0]) ; /* volumes or slices */
643
644 for( tt=0 ; tt < DSET_NVALS(RT_dset[0]) ; tt++ ){ /* loop over time points */
645
646 if( RT_3D ){ /** send 3D arrays **/
647
648 for( cc=0 ; cc < num_chan ; cc++ ){ /* loop over channels (datasets) */
649
650 bar = DSET_ARRAY(RT_dset[cc],tt) ; /* array to send */
651
652 if( AFNI_verbose )
653 fprintf(stderr,"--- Sending brick %d, channel %02d\n",tt,cc+1) ;
654
655 if( RT_dt > 0.0 ) start_time = COX_clock_time() ;
656
657 sar = bar ;
658 if( RT_swap2 ){ /* swap bytes? */
659 memcpy(qar,sar,nbytes) ; sar = qar ;
660 mri_swap2( nbytes/2 , (short *) sar ) ;
661 }
662
663 /* send the whole 3D array (sar points to data to transmit) */
664
665 ii = iochan_sendall( AFNI_ioc , sar , nbytes ) ;
666 if( ii < 0 ){
667 fprintf(stderr,
668 "*** Error sending brick %d, channel %02d, to AFNI\n",
669 tt,cc+1) ;
670 exit(1) ;
671 }
672
673 /* maybe wait for prescribed transmission time */
674
675 if( RT_dt > 0.0 ){
676 left_time = RT_dt - ( COX_clock_time() - start_time ) ;
677 if( left_time >= 0.001 ){
678 ii = (int) (1000.0 * left_time) ; /* number of milliseconds */
679 iochan_sleep( ii ) ;
680 }
681 }
682 } /* end of loop over channels */
683
684 /** send 2D slices from each channel in turn **/
685
686 } else {
687
688 for( kk=0 ; kk < DSET_NZ(RT_dset[0]) ; kk++ ){ /* loop over slices */
689 for( cc=0 ; cc < num_chan ; cc++ ){ /* loop over channels */
690
691 bar = DSET_ARRAY(RT_dset[cc],tt) ; /* 3D array to get slice from */
692
693 if( AFNI_verbose )
694 fprintf(stderr,"--- Sending brick %d, slice %d, channel %02d\n",
695 tt,kk,cc+1) ;
696
697 if( RT_dt > 0.0 ) start_time = COX_clock_time() ;
698
699 sar = bar+(kk*nbslice) ; /* pointer to start of slice data */
700
701 if( RT_swap2 ){ /* byte swapping */
702 memcpy(qar,sar,nbslice) ; sar = qar ;
703 mri_swap2( nbslice/2 , (short *) sar ) ;
704 }
705
706 /* send slice data */
707
708 ii = iochan_sendall( AFNI_ioc , sar , nbslice ) ;
709
710 if( ii < 0 ){
711 fprintf(stderr,
712 "*** Error sending slice brick %d, slice %d, channel %02d to AFNI\n",
713 tt,kk,cc+1) ;
714 exit(1) ;
715 }
716
717 if( RT_dt > 0.0 ){ /* wait for prescribed transmission time */
718 left_time = RT_dt - ( COX_clock_time() - start_time ) ;
719 if( left_time >= 0.001 ){
720 ii = (int) (1000.0 * left_time) ;
721 iochan_sleep( ii ) ;
722 }
723 }
724
725 } /* end of loop over channels */
726 } /* end of loop over slices */
727
728 } /* end of if 3D or 2D transmissions */
729
730 /** unload dataset bricks we just sent **/
731
732 for( cc=0 ; cc < num_chan ; cc++ )
733 DSET_unload_one( RT_dset[cc] , tt ) ;
734
735 } /* end of loop over time points */
736
737 /*-- cleanup --*/
738
739 xtime = COX_clock_time() - xtime ; /* total transmit time */
740
741 for( cc=0 ; cc < num_chan ; cc++ ) /* unload all datasets */
742 DSET_delete( RT_dset[cc] ) ;
743
744 /* make sure all data is transmitted to AFNI */
745
746 if( AFNI_verbose ) fprintf(stderr,"--- Clearing buffer") ;
747 iochan_sleep(100) ;
748 while( ! iochan_clearcheck(AFNI_ioc,100) ){
749 if( AFNI_verbose ) fprintf(stderr,".") ;
750 }
751 if( AFNI_verbose ) fprintf(stderr,"\n") ;
752
753 fprintf(stderr,
754 "--- Elapsed transmit time = %f s (%f per transmit)\n",
755 xtime,xtime/ntran) ;
756
757 /*-- If we are going to restart, send the end-of-input message. --*/
758 /*-- Note that an entire image must be sent with this message. --*/
759
760 if( iarg < argc ){
761 fprintf(stderr,"--- Restarting after '-break'\n") ;
762 memcpy( qar , COMMAND_MARKER , COMMAND_MARKER_LENGTH ) ;
763 iochan_sendall( AFNI_ioc , qar , nbytes ) ;
764 iochan_sleep(1000*bwait) ; /* let AFNI meditate on that for a while */
765 goto Restart ;
766 }
767
768 /*-- Otherwise, quit. --*/
769
770 exit(0) ;
771 }
772