1 #include "mrilib.h"
2 
3 #define FatalError(str) \
4    ( fprintf(stderr,"\nEPsim error: %s\n",(str)) , exit(1) )
5 
6 static int use_shm    = 1 ;
7 static int delay      = 100 ;
8 static int use_child  = 0 ;
9 static int use_3T     = 0 ;
10 char *     fname_3T   = NULL ;
11 static int ntimes     = 1 ;
12 static char host[128] = "localhost" ;
13 static char buf[4096] ;
14 static int  nbytes , jj , first=1 ;
15 
16 #if 0 /*  ZSS June 2011. Delete useless code after dust has settled.  */
17    #define CONTROL_PORT 7954
18    #define TCP_PORT     7955
19    /* replace with:
20       get_port_named("CONTROL_PORT")
21       get_port_named("AFNI_PLUGOUT_TCP_BASE")
22    */
23 #endif
24 #define SHM_NAME     "shm:epsim:1M"
25 
26 static IOCHAN * ioc = NULL ;
27 
28 #define SHORT_DELAY      1            /* msec */
29 #define LONG_DELAY      10
30 
31 /*---------------------------------------------------------------------------*/
32 
Syntax(void)33 void Syntax(void)
34 {
35    printf(
36     "Program:   epsim \n\n"
37     "Purpose:   Extract 2D data files from 3D dataset & send to AFNI\n"
38     "Usage:     epsim [-v] [-shm | -tcp] [-delay mmm] [-host cpu] [-child]\n"
39     "                 -input fname \n"
40     "Options: 	\n"
41     "-v                 Print out verbose information.\n"
42 #if 0
43     "-nsize             Adjust size of 2d data file to be NxN, by padding \n"
44     "                     with zeros, where N is a power of 2. \n"
45 #endif
46     "-shm               Use shared memory to communicate with AFNI. \n"
47     "-tcp               Use TCP/IP to communicate with AFNI. \n"
48     "-delay mmm         Delay mmm milliseconds between slices. \n"
49     "-host cpu          Access AFNI on host named 'cpu'. \n"
50     "-child             Tell AFNI to read header info from a child. \n"
51     "-3T fname          Tell AFNI to get data from the 3T_toafni program\n"
52     "                     with the 3T control data stored in file 'fname'.\n"
53     "-input fname       Read from dataset in file 'fname'. \n"
54     "-times n           Send the dataset 'n' times.\n"
55    ) ;
56    exit(0) ;
57 }
58 
59 /*---------------------------------------------------------------------------*/
60 
F3D_initialize_user_data(int Argc,char * Argv[],RwcBoolean * verbose,RwcBoolean * nsize,int * zfirst,int * zlast,int * tfirst,int * tlast,char * input_filename,char * prefix_filename)61 void F3D_initialize_user_data ( int Argc, char * Argv[],
62    RwcBoolean * verbose, RwcBoolean * nsize,
63    int * zfirst, int * zlast, int * tfirst, int * tlast,
64    char * input_filename, char * prefix_filename )
65 
66 {
67    const int BIGNUMBER = 10000;
68    int nopt;
69    float ftemp;
70 
71    if (Argc < 2)  Syntax();
72 
73    /* --- set default values --- */
74    *verbose = FALSE;
75    *nsize = FALSE;
76    *zfirst = 1;
77    *zlast = BIGNUMBER;
78    *tfirst = 1;
79    *tlast = BIGNUMBER;
80    strcpy(input_filename, "");
81    strcpy(prefix_filename, "");
82 
83 
84    /* --- scan options --- */
85    nopt = 1 ;
86    while ( nopt < Argc && Argv[nopt][0] == '-' )
87    {
88 
89        /* --- help option --- */
90       if ( strncmp(Argv[nopt],"-help",4) == 0 )  Syntax() ;
91 
92       /* --- verbose option --- */
93       if ( strncmp(Argv[nopt],"-v",2) == 0 )
94       {
95          *verbose = TRUE;
96          nopt++ ;
97          continue;
98       }
99 #if 0
100       /* --- nsize option --- */
101       if ( strncmp(Argv[nopt],"-nsize",4) == 0 )
102       {
103          *nsize = TRUE;
104          nopt++ ;
105          continue;
106       }
107 #endif
108 
109       /*-- -times n --*/
110       if( strncmp(Argv[nopt],"-times",4) == 0 ){
111          if( ++nopt >= Argc ) FatalError("-times needs an argument") ;
112          ftemp = strtod( Argv[nopt] , NULL ) ;
113          if( ftemp >= 1.0 ) ntimes = (int) ftemp ;
114          nopt++ ; continue ;
115       }
116 
117 #if 0
118       /* --- zfirst option --- */
119       if ( strncmp(Argv[nopt],"-zfirst",4) == 0 )
120       {
121          if( ++nopt >= Argc ) FatalError("-zfirst needs an argument") ;
122          ftemp = strtod( Argv[nopt] , NULL ) ;
123          *zfirst = (int) ftemp ;
124          nopt++ ;
125          continue ;
126       }
127 
128       /* --- zlast option --- */
129       if ( strncmp(Argv[nopt],"-zlast",4) == 0 )
130       {
131          if( ++nopt >= Argc ) FatalError("-zlast needs an argument") ;
132          ftemp = strtod( Argv[nopt] , NULL ) ;
133          *zlast = (int) ftemp ;
134          nopt++ ;
135          continue ;
136       }
137 
138       /* --- tfirst option --- */
139       if ( strncmp(Argv[nopt],"-tfirst",4) == 0 )
140       {
141          if( ++nopt >= Argc ) FatalError("-tfirst needs an argument") ;
142          ftemp = strtod( Argv[nopt] , NULL ) ;
143          *tfirst = (int) ftemp ;
144          nopt++ ;
145          continue ;
146       }
147 
148       /* --- tlast option --- */
149       if ( strncmp(Argv[nopt],"-tlast",4) == 0 )
150       {
151          if( ++nopt >= Argc ) FatalError("-tlast needs an argument") ;
152          ftemp = strtod( Argv[nopt] , NULL ) ;
153          *tlast = (int) ftemp ;
154          nopt++ ;
155          continue ;
156       }
157 #endif
158 
159       if( strncmp(Argv[nopt],"-shm",4) == 0 ){
160          use_shm = 1 ;
161          nopt++ ; continue ;
162       }
163 
164       if( strncmp(Argv[nopt],"-tcp",4) == 0 ){
165          use_shm = 0 ;
166          nopt++ ; continue ;
167       }
168 
169       if( strncmp(Argv[nopt],"-child",4) == 0 ){
170          use_child = 1 ;
171          nopt++ ; continue ;
172       }
173 
174       if( strncmp(Argv[nopt],"-3T",4) == 0 ){
175          if( ++nopt >= Argc ) FatalError("-3T needs a filename") ;
176          fname_3T = Argv[nopt] ;
177          use_3T = 1 ;
178          nopt++ ; continue ;
179       }
180 
181       if( strncmp(Argv[nopt],"-delay",4) == 0 ){
182          if ( ++nopt >= Argc ) FatalError("-delay needs a number") ;
183          ftemp = strtod( Argv[nopt] , NULL ) ;
184          if( ftemp >= 0.0 ) delay = (int) ftemp ;
185          nopt++ ; continue ;
186       }
187 
188       if( strncmp(Argv[nopt],"-host",4) == 0 ){
189          if ( ++nopt >= Argc ) FatalError("-host needs a cpu name") ;
190          strcpy( host , Argv[nopt] ) ;
191          nopt++ ; continue ;
192       }
193 
194       /* --- input file name --- */
195       if ( strncmp(Argv[nopt],"-input",4) == 0 )
196       {
197          if ( ++nopt >= Argc ) FatalError("-input needs a name") ;
198          strcpy ( input_filename , Argv[nopt] ) ;
199          nopt++ ; continue ;
200       }
201 
202 #if 0
203       /* --- prefix name --- */
204       if ( strncmp(Argv[nopt],"-prefix",4) == 0 )
205       {
206          if ( ++nopt >= Argc ) FatalError("-prefix needs a name") ;
207          strcpy ( prefix_filename , Argv[nopt] ) ;
208          nopt++ ; continue ;
209       }
210 #endif
211 
212       /* --- exception --- */
213       fprintf(stderr,"Don't understand argument %s\n",Argv[nopt]) ;
214       FatalError ("Illegal input");
215 
216    }  /* nopt */
217 
218    /* --- check for valid inputs --- */
219 #if 0
220    if (*zfirst > *zlast)
221       FatalError ("Cannot have zfirst > zlast");
222    if (*tfirst > *tlast)
223       FatalError ("Cannot have tfirst > tlast");
224    if (!strcmp(prefix_filename,""))
225       FatalError ("Must specify prefix file name.");
226 #endif
227    if (!strcmp(input_filename,""))
228       FatalError ("Must specify input file name. ");
229 
230    if( strcmp(host,"localhost") != 0 && use_shm ){
231       printf("EPsim: must use TCP/IP for host %s\n",host) ;
232       use_shm = 0 ;
233    }
234 
235    if( use_child && use_3T )
236       FatalError("Can't use -child and -3T together!") ;
237 
238    return;
239 }
240 
241 /*---------------------------------------------------------------------------*/
242 
main(int argc,char * argv[])243 int main( int argc , char * argv[] )
244 {
245    /* --- variable declarations --- */
246    THD_3dim_dataset * dset ;
247    THD_diskptr * dskptr;
248    int nx, ny, nz, nv, itim;
249    RwcBoolean verbose, nsize;
250    int ok;
251    MRI_IMAGE * im, * im2d, * tim2d;
252    MRI_TYPE kind;
253    int ibr, iz, count, izz,izsub ;
254    int zfirst, zlast, tfirst, tlast;
255    char input_filename[THD_MAX_NAME],
256         prefix_filename[THD_MAX_NAME],
257         output_filename[THD_MAX_NAME],
258         str[THD_MAX_NAME];
259 
260    /* --- get user command line inputs --- */
261    F3D_initialize_user_data (argc, argv,
262       &verbose, &nsize,
263       &zfirst, &zlast, &tfirst, &tlast,
264       input_filename, prefix_filename );
265 
266    /* --- open 3d data set --- */
267    dset = THD_open_one_dataset( input_filename ) ;
268    if( dset == NULL )  FatalError ("Unable to open input file") ;
269    if ( verbose )  printf("EPsim: 3d Dataset File = %s\n" , input_filename ) ;
270 
271    /* --- load data block --- */
272    ok = THD_load_datablock( dset->dblk );
273    if ( !ok )  FatalError ("Unable to load data block") ;
274 
275    /* --- get data dimensions --- */
276    dskptr = dset->dblk->diskptr;
277    nx = dskptr->dimsizes[0];
278    ny = dskptr->dimsizes[1];
279    nz = dskptr->dimsizes[2];
280    nv = dskptr->nvals;
281    if ( verbose )
282       printf ("EPsim: nx=%d  ny=%d  nz=%d  nv=%d\n",   nx, ny, nz, nv);
283 
284    /* --- check for valid user inputs --- */
285    if (zfirst < 1) zfirst = 1;
286    if (zlast > nz) zlast = nz;
287    if (tfirst < 1) tfirst = 1;
288    if (tlast > nv) tlast = nv;
289    if (zfirst > nz)  FatalError ("No data selected -- zfirst too large.");
290    if (zlast < 1)    FatalError ("No data selected -- zlast too small.");
291    if (tfirst > nv)  FatalError ("No data selected -- tfirst too large.");
292    if (tlast < 1)    FatalError ("No data selected -- tlast too small.");
293 
294    /* --- get data type --- */
295    kind = IMAGE_IN_IMARR ( dset->dblk->brick, 0 ) -> kind;
296    if ( verbose )  printf ("EPsim: datum = %s \n", MRI_TYPE_name[kind]);
297 
298    /* --- create 2d data pointer --- */
299    im2d = mri_new_vol_empty ( nx, ny, 1, kind );
300 
301    /*** open channel to AFNI ***/
302 
303    sprintf( buf , "tcp:%s:%d" , host , get_port_named("CONTROL_PORT") ) ;
304    ioc = iochan_init( buf , "create" ) ;
305    if( ioc == NULL ) FatalError("Cannot open control channel to AFNI") ;
306 
307    if( verbose ) printf("EPsim: waiting for AFNI") ; fflush(stdout) ;
308 
309    while(1){
310       iz = iochan_goodcheck( ioc , 1000 ) ;
311       if( iz < 0 ) FatalError("control channel failed") ;
312       if( iz > 0 ) break ;
313       if( verbose ){ printf(".") ; fflush(stdout) ; }
314    }
315    if( verbose ){ printf("!\n") ; fflush(stdout) ; }
316 
317    if( use_shm ) strcpy( buf , SHM_NAME ) ;
318    else          sprintf(buf , "tcp:%s:%d" ,
319                          host , get_port_named("AFNI_PLUGOUT_TCP_BASE") ) ;
320 
321    if( use_child ){
322       jj = strlen(buf) ;
323       sprintf(buf+jj,"\ncat epsim.out") ;
324    } else if( use_3T ){
325       jj = strlen(buf) ;
326       sprintf(buf+jj,"\n3T_toafni -dummy < %s" , fname_3T ) ;
327    }
328 
329    if( verbose ) printf("sending control data: %s\n",buf) ;
330 
331    jj = iochan_sendall( ioc , buf , strlen(buf)+1 ) ;
332    if( jj < 0 ) FatalError("send control data failed") ;
333    iochan_sleep(LONG_DELAY) ;                      /* wait a bit */
334    while( ! iochan_clearcheck(ioc,LONG_DELAY) )    /* loop until cleared */
335       iochan_sleep(LONG_DELAY) ;
336 
337    if( verbose ) printf("EPsim: closing control channel\n") ;
338    IOCHAN_CLOSE(ioc) ;
339 
340    /*** now open data channel ***/
341 
342    ioc = iochan_init( buf , "create" ) ;
343    if( ioc == NULL ) FatalError("Cannot open data channel to AFNI") ;
344 
345    if( verbose ) printf("EPsim: waiting for AFNI") ; fflush(stdout) ;
346 
347    while(1){
348       iz = iochan_goodcheck( ioc , 1000 ) ;
349       if( iz < 0 ) FatalError("data channel failed") ;
350       if( iz > 0 ) break ;
351       if( verbose ){ printf(".") ; fflush(stdout) ; }
352    }
353    if( verbose ){ printf("!\n") ; fflush(stdout) ; }
354 
355    if( use_child ){
356       FILE * fp = fopen( "epsim.out" , "w" ) ;
357       if( fp == NULL ){fprintf(stderr,"Can't open epsim.out!\n");IOCHAN_CLOSE(ioc);exit(1);}
358       fprintf( fp ,  "ZNUM %d\n"
359                      "ZDELTA %g\n"
360                      "XYFOV %g %g\n"
361                      "ZFIRST %g%c\n"
362                      "ZORDER seq\n"
363                      "XYZAXES %s %s %s\n"
364                      "ACQUISITION_TYPE %s\n"
365                    ,
366                      nz ,
367                      fabs(dset->daxes->zzdel) ,
368                      fabs(dset->daxes->xxdel)*nx , fabs(dset->daxes->yydel)*ny ,
369                      fabs(dset->daxes->zzorg) , ORIENT_first[dset->daxes->zzorient] ,
370                      ORIENT_shortstr[dset->daxes->xxorient] ,
371                        ORIENT_shortstr[dset->daxes->yyorient] ,
372                        ORIENT_shortstr[dset->daxes->zzorient] ,
373                      ( ((zlast-zfirst)>0) ? "2D+zt" : "2D+z" )
374                    ) ;
375       fclose(fp) ;
376       if( verbose ) printf("EPsim: wrote epsim.out file\n") ;
377 
378       sprintf( buf , "XYMATRIX %d %d\n"
379                      "DATUM %s\n"
380                    ,
381                      nx , ny ,
382                      MRI_TYPE_name[kind]
383                    ) ;
384    } else if( use_3T ){
385       sprintf( buf , "XYMATRIX %d %d\n"
386                      "DATUM %s\n"
387                    ,
388                      nx , ny ,
389                      MRI_TYPE_name[kind]
390                    ) ;
391    } else {
392       sprintf( buf , "ZNUM %d\n"
393                      "ZDELTA %g\n"
394                      "XYFOV %g %g\n"
395                      "ZFIRST %g%c\n"
396                      "ZORDER seq\n"
397                      "XYZAXES %s %s %s\n"
398                      "ACQUISITION_TYPE %s\n"
399                      "XYMATRIX %d %d\n"
400                      "DATUM %s\n"
401                    ,
402                      nz ,
403                      fabs(dset->daxes->zzdel) ,
404                      fabs(dset->daxes->xxdel)*nx , fabs(dset->daxes->yydel)*ny ,
405                      fabs(dset->daxes->zzorg) , ORIENT_first[dset->daxes->zzorient] ,
406                      ORIENT_shortstr[dset->daxes->xxorient] ,
407                        ORIENT_shortstr[dset->daxes->yyorient] ,
408                        ORIENT_shortstr[dset->daxes->zzorient] ,
409                      ( ((zlast-zfirst)>0) ? "2D+zt" : "2D+z" ) ,
410                      nx , ny ,
411                      MRI_TYPE_name[kind]
412                    ) ;
413    }
414 
415    nbytes = im2d->nvox * im2d->pixel_size ;
416 
417    for( itim=0 ; itim < ntimes ; itim++ ){
418    count = 0;
419 
420    if( use_3T ) izsub = (nz%2 == 0) ? (nz-1) : (nz) ;
421 
422    for ( ibr = tfirst-1 ; ibr < tlast ; ibr++ )
423    {
424       for ( iz = zfirst-1 ; iz < zlast ; iz++ )
425       {
426          /* --- set 2d data pointer into 3d data set --- */
427          im = IMAGE_IN_IMARR ( dset->dblk->brick, ibr );
428 
429          if( use_3T ){
430            izz = 2*iz ; if( izz >= nz ) izz -= izsub ;  /* alt ordering */
431          } else {
432            izz = iz ;                                   /* seq ordering */
433          }
434 
435          switch ( kind )
436          {
437             case MRI_byte :
438                mri_set_data_pointer(im2d, MRI_BYTE_PTR(im) + iz*nx*ny) ;
439             break;
440             case MRI_short :
441                mri_set_data_pointer(im2d, MRI_SHORT_PTR(im) + iz*nx*ny) ;
442             break;
443             case MRI_int :
444                mri_set_data_pointer(im2d, MRI_INT_PTR(im) + iz*nx*ny) ;
445             break;
446             case MRI_float :
447                mri_set_data_pointer(im2d, MRI_FLOAT_PTR(im) + iz*nx*ny) ;
448             break;
449             case MRI_double :
450                mri_set_data_pointer(im2d, MRI_DOUBLE_PTR(im) + iz*nx*ny) ;
451             break;
452             case MRI_complex :
453                mri_set_data_pointer(im2d, MRI_COMPLEX_PTR(im) + iz*nx*ny) ;
454             break;
455             case MRI_rgb :
456                mri_set_data_pointer(im2d, MRI_RGB_PTR(im) + 3*iz*nx*ny) ;
457             break;
458             default :
459                FatalError ("Illegal data type encountered.");
460          }
461 
462 #if 0
463          /* --- create 2d data file name --- */
464          strcpy ( output_filename, prefix_filename );
465          if ( nv > 1 )
466             sprintf ( str, "%02d.%04d", izz+1, ibr+1 );
467          else
468             if ( nz > 999 )
469                sprintf ( str, ".%04d", izz+1 );
470             else
471                sprintf ( str, ".%03d", izz+1 );
472          strcat ( output_filename, str );
473 #endif
474 
475          if( first ){
476             if( verbose )
477                printf("EPsim: sending this data as header info in image channel:\n%s\n",buf) ;
478             jj = iochan_sendall( ioc , buf , strlen(buf)+1 ) ;
479             if( jj < 0 ) FatalError("send header info failed") ;
480             first = 0 ;
481          }
482 
483          if ( verbose )
484             printf ( "EPsim: sending 2D image izz=%d ibr=%d\n", izz,ibr );
485 
486          jj = iochan_sendall( ioc , mri_data_pointer(im2d) , nbytes ) ;
487          if( jj < 0 ) FatalError("send image failed") ;
488          iochan_sleep( delay ) ;
489 
490 #if 0
491          if ( !nsize )
492             ok = mri_write ( output_filename, im2d );
493          else
494          {
495             tim2d = mri_nsize (im2d);
496             ok = mri_write ( output_filename, tim2d);
497             mri_free (tim2d);
498          }
499 #endif
500 
501          count ++ ;
502 
503       }  /* --- iz --- */
504    }  /* --- ibr --- */
505    sleep(20) ;
506    } /* -- itim --*/
507 
508    if ( verbose )  printf ("Sent %d 2D images. \n", count);
509 
510    if( verbose ){ printf("Waiting for AFNI") ; fflush(stdout) ; }
511    while(1){
512       jj = iochan_clearcheck(ioc,1000) ;
513       if( jj ) break ;
514       if( verbose ){ printf(".") ; fflush(stdout) ; }
515    }
516    if( verbose ) printf("!\n") ;
517    iochan_sleep(100) ; IOCHAN_CLOSE(ioc) ;
518 
519    exit(0) ;
520 }
521