00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #define ALLOW_BUCKETS
00036 #define ALLOW_SUBV
00037
00038 #include "mrilib.h"
00039 #include "parser.h"
00040
00041 #ifndef myXtFree
00042 #define myXtFree(xp) (XtFree((char *)(xp)) , (xp)=NULL)
00043 #endif
00044
00045
00046
00047 static int CALC_datum = ILLEGAL_TYPE ;
00048 static int CALC_nvox = -1 ;
00049 static PARSER_code * CALC_code = NULL ;
00050 static int ntime[26] ;
00051 static int ntime_max = 0 ;
00052 static int CALC_fscale = 0 ;
00053 static int CALC_gscale = 0 ;
00054 static int CALC_nscale = 0 ;
00055
00056 static int CALC_histpar = -1 ;
00057
00058
00059
00060 #define DSHIFT_MODE_STOP 0
00061 #define DSHIFT_MODE_WRAP 1
00062 #define DSHIFT_MODE_ZERO 2
00063
00064 static int CALC_dshift [26] ;
00065 static int CALC_dshift_i [26] ;
00066 static int CALC_dshift_j [26] ;
00067 static int CALC_dshift_k [26] ;
00068 static int CALC_dshift_l [26] ;
00069 static int CALC_dshift_mode[26] ;
00070
00071 static int CALC_dshift_mode_current = DSHIFT_MODE_STOP ;
00072 static int CALC_has_timeshift = 0 ;
00073
00074
00075
00076 static int CALC_has_sym[26] ;
00077 static char abet[] = "abcdefghijklmnopqrstuvwxyz" ;
00078
00079 #define HAS_I CALC_has_sym[ 8]
00080 #define HAS_J CALC_has_sym[ 9]
00081 #define HAS_K CALC_has_sym[10]
00082 #define HAS_X CALC_has_sym[23]
00083 #define HAS_Y CALC_has_sym[24]
00084 #define HAS_Z CALC_has_sym[25]
00085 #define HAS_T CALC_has_sym[19]
00086 #define HAS_L CALC_has_sym[11]
00087
00088 #define PREDEFINED_MASK ((1<< 8)|(1<< 9)|(1<<10)|(1<<11)| \
00089 (1<<19)|(1<<23)|(1<<24)|(1<<25) )
00090
00091 static int CALC_has_predefined = 0 ;
00092 static int CALC_has_xyz = 0 ;
00093 static int CALC_mangle_xyz = 0 ;
00094
00095 #define MANGLE_NONE 0
00096 #define MANGLE_RAI 1
00097 #define MANGLE_LPI 2
00098
00099 static THD_3dim_dataset * CALC_dset[26] ;
00100 static int CALC_type[26] ;
00101 static byte ** CALC_byte[26] ;
00102 static short ** CALC_short[26] ;
00103 static float ** CALC_float[26] ;
00104 static float * CALC_ffac[26] ;
00105 static int CALC_noffac[26] ;
00106
00107 static int CALC_verbose = 0 ;
00108
00109 static char CALC_output_prefix[THD_MAX_PREFIX] = "calc" ;
00110
00111 static char CALC_session[THD_MAX_NAME] = "./" ;
00112
00113 static MRI_IMAGE * TS_flim[26] ;
00114 static float * TS_flar[26] ;
00115 static int TS_nmax = 0 ;
00116 static int TS_make = 0 ;
00117 static float TS_dt = 1.0 ;
00118
00119 static MRI_IMAGE * IJKAR_flim[26] ;
00120 static float * IJKAR_flar[26] ;
00121 static int IJKAR_dcod[26] ;
00122
00123
00124
00125
00126 #define VAR_DEFINED(kv) \
00127 (TS_flim[kv] != NULL || IJKAR_flim[kv] != NULL || \
00128 CALC_dset[kv] != NULL || CALC_dshift[kv] >= 0 )
00129
00130 static float Rfac = 0.299 ;
00131 static float Gfac = 0.587 ;
00132 static float Bfac = 0.114 ;
00133
00134 static int CALC_taxis_num = 0 ;
00135
00136
00137 void CALC_read_opts( int , char ** ) ;
00138 void CALC_Syntax(void) ;
00139 int TS_reader( int , char * ) ;
00140 int IJKAR_reader( int , char * ) ;
00141
00142
00143
00144
00145
00146
00147 int TS_reader( int ival , char *fname )
00148 {
00149 MRI_IMAGE *tsim ;
00150
00151 if( ival < 0 || ival >= 26 ) return -1 ;
00152
00153 tsim = mri_read_1D( fname ) ;
00154 if( tsim == NULL ) return -1 ;
00155 if( tsim->nx < 2 ){ mri_free(tsim) ; return -1 ; }
00156
00157 TS_flim[ival] = tsim ;
00158 TS_nmax = MAX( TS_nmax , TS_flim[ival]->nx ) ;
00159 TS_flar[ival] = MRI_FLOAT_PTR( TS_flim[ival] ) ;
00160 return 0 ;
00161 }
00162
00163
00164
00165
00166
00167
00168 int IJKAR_reader( int ival , char *fname )
00169 {
00170 MRI_IMAGE *tsim ;
00171
00172 if( ival < 0 || ival >= 26 ) return -1 ;
00173
00174 tsim = mri_read_1D( fname ) ;
00175 if( tsim == NULL ) return -1 ;
00176 if( tsim->nx < 2 ){ mri_free(tsim) ; return -1 ; }
00177
00178 IJKAR_flim[ival] = tsim ;
00179 IJKAR_flar[ival] = MRI_FLOAT_PTR( IJKAR_flim[ival] ) ;
00180 return 0 ;
00181 }
00182
00183
00184
00185
00186
00187 void CALC_read_opts( int argc , char * argv[] )
00188 {
00189 int nopt = 1 ;
00190 int ids ;
00191 int ii, kk;
00192
00193 for( ids=0 ; ids < 26 ; ids++ ){
00194 CALC_dset[ids] = NULL ;
00195 CALC_type[ids] = -1 ;
00196 TS_flim[ids] = NULL ;
00197 IJKAR_flim[ids] = NULL ;
00198
00199 CALC_dshift[ids] = -1 ;
00200 CALC_dshift_mode[ids] = CALC_dshift_mode_current ;
00201
00202 CALC_noffac[ids] = 1 ;
00203 }
00204
00205 while( nopt < argc && argv[nopt][0] == '-' ){
00206
00207
00208
00209 if( strcasecmp(argv[nopt],"-dicom") == 0 || strcasecmp(argv[nopt],"-rai") == 0 ){
00210 CALC_mangle_xyz = MANGLE_RAI ;
00211 nopt++ ; continue ;
00212 }
00213
00214 if( strcasecmp(argv[nopt],"-spm") == 0 || strcasecmp(argv[nopt],"-lpi") == 0 ){
00215 CALC_mangle_xyz = MANGLE_LPI ;
00216 nopt++ ; continue ;
00217 }
00218
00219
00220
00221 if( strncasecmp(argv[nopt],"-rgbfac",7) == 0 ){
00222 if( ++nopt >= argc )
00223 ERROR_exit("need an argument after -rgbfac!\n") ;
00224 Rfac = strtod( argv[nopt++] , NULL ) ;
00225 Gfac = strtod( argv[nopt++] , NULL ) ;
00226 Bfac = strtod( argv[nopt++] , NULL ) ;
00227 if( Rfac == 0.0 && Gfac == 0.0 && Bfac == 0.0 )
00228 ERROR_exit("All 3 factors after -rgbfac are zero!?\n");
00229 continue ;
00230 }
00231
00232
00233
00234 if( strncasecmp(argv[nopt],"-taxis",6) == 0 ){
00235 char *cpt ;
00236 if( ++nopt >= argc )
00237 ERROR_exit("need an argument after -taxis!\n") ;
00238 CALC_taxis_num = strtod( argv[nopt] , &cpt ) ;
00239 if( CALC_taxis_num < 2 )
00240 ERROR_exit("N value after -taxis must be bigger than 1!\n");
00241 if( *cpt == ':' ){
00242 float dt = strtod( cpt+1 , &cpt ) ;
00243 if( dt > 0.0 ){
00244 TS_dt = dt ;
00245 if( *cpt == 'm' && *(cpt+1) == 's' ) TS_dt *= 0.001 ;
00246 } else {
00247 WARNING_message("time step value in '-taxis %s' not legal!\n",argv[nopt]);
00248 }
00249 }
00250 nopt++ ; continue ;
00251 }
00252
00253
00254
00255 if( strncasecmp(argv[nopt],"-dt",3) == 0 || strncmp(argv[nopt],"-TR",3) == 0 ){
00256 char *cpt ;
00257 if( ++nopt >= argc )
00258 ERROR_exit("need an argument after -dt!\n") ;
00259 TS_dt = strtod( argv[nopt] , &cpt ) ;
00260 if( TS_dt <= 0.0 )
00261 ERROR_exit("Illegal time step value after -dt!\n");
00262 if( *cpt == 'm' && *(cpt+1) == 's' ) TS_dt *= 0.001 ;
00263 nopt++ ; continue ;
00264 }
00265
00266
00267
00268 if( strncasecmp(argv[nopt],"-histpar",5) == 0 ){
00269 if( ++nopt >= argc )
00270 ERROR_exit("need an argument after -histpar!\n") ;
00271 if( argv[nopt][0] < 'a' || argv[nopt][0] > 'z')
00272 ERROR_exit("argument after -histpar is illegal!\n");
00273 CALC_histpar = (int) (argv[nopt][0] - 'a') ;
00274
00275 nopt++ ; continue ;
00276 }
00277
00278
00279
00280 if( strncasecmp(argv[nopt],"-datum",6) == 0 ){
00281 if( ++nopt >= argc )
00282 ERROR_exit("need an argument after -datum!\n") ;
00283 if( strcasecmp(argv[nopt],"short") == 0 ){
00284 CALC_datum = MRI_short ;
00285 } else if( strcasecmp(argv[nopt],"float") == 0 ){
00286 CALC_datum = MRI_float ;
00287 } else if( strcasecmp(argv[nopt],"byte") == 0 ){
00288 CALC_datum = MRI_byte ;
00289 } else if( strcasecmp(argv[nopt],"complex") == 0 ){
00290 CALC_datum = MRI_complex ;
00291 } else {
00292 ERROR_exit("-datum of type '%s' not supported in 3dcalc!\n",argv[nopt]) ;
00293 }
00294 nopt++ ; continue ;
00295 }
00296
00297
00298
00299 if( strncasecmp(argv[nopt],"-verbose",5) == 0 ){
00300 CALC_verbose = 1 ;
00301 nopt++ ; continue ;
00302 }
00303
00304
00305
00306 if( strncasecmp(argv[nopt],"-nscale",6) == 0 ){
00307 CALC_gscale = CALC_fscale = 0 ;
00308 CALC_nscale = 1 ;
00309 nopt++ ; continue ;
00310 }
00311
00312
00313
00314 if( strncasecmp(argv[nopt],"-fscale",6) == 0 ){
00315 CALC_fscale = 1 ;
00316 CALC_nscale = 0 ;
00317 nopt++ ; continue ;
00318 }
00319
00320
00321
00322 if( strncasecmp(argv[nopt],"-gscale",6) == 0 ){
00323 CALC_gscale = CALC_fscale = 1 ;
00324 CALC_nscale = 0 ;
00325 nopt++ ; continue ;
00326 }
00327
00328
00329
00330 if( strncasecmp(argv[nopt],"-prefix",6) == 0 ){
00331 nopt++ ;
00332 if( nopt >= argc )
00333 ERROR_exit("need argument after -prefix!\n") ;
00334 MCW_strncpy( CALC_output_prefix , argv[nopt++] , THD_MAX_PREFIX ) ;
00335 continue ;
00336 }
00337
00338
00339
00340 if( strncasecmp(argv[nopt],"-session",6) == 0 ){
00341 nopt++ ;
00342 if( nopt >= argc )
00343 ERROR_exit("need argument after -session!\n") ;
00344 MCW_strncpy( CALC_session , argv[nopt++] , THD_MAX_NAME ) ;
00345 continue ;
00346 }
00347
00348
00349
00350 if( strncasecmp(argv[nopt],"-expr",4) == 0 ){
00351 if( CALC_code != NULL )
00352 ERROR_exit("cannot have 2 -expr options!\n") ;
00353 nopt++ ;
00354 if( nopt >= argc )
00355 ERROR_exit("need argument after -expr!\n") ;
00356 PARSER_set_printout(1) ;
00357 CALC_code = PARSER_generate_code( argv[nopt++] ) ;
00358 if( CALC_code == NULL )
00359 ERROR_exit("illegal expression!\n") ;
00360 PARSER_mark_symbols( CALC_code , CALC_has_sym ) ;
00361 continue ;
00362 }
00363
00364
00365
00366 if( strncasecmp(argv[nopt],"-dsSTOP",6) == 0 ){
00367 CALC_dshift_mode_current = DSHIFT_MODE_STOP ;
00368 nopt++ ; continue ;
00369 }
00370
00371
00372
00373 if( strncasecmp(argv[nopt],"-dsWRAP",6) == 0 ){
00374 CALC_dshift_mode_current = DSHIFT_MODE_WRAP ;
00375 nopt++ ; continue ;
00376 }
00377
00378
00379
00380 if( strncasecmp(argv[nopt],"-dsZERO",6) == 0 ){
00381 CALC_dshift_mode_current = DSHIFT_MODE_ZERO ;
00382 nopt++ ; continue ;
00383 }
00384
00385
00386
00387 ids = strlen( argv[nopt] ) ;
00388
00389 if( (argv[nopt][1] >= 'a' && argv[nopt][1] <= 'z') &&
00390 (ids == 2 ||
00391 (ids > 2 && argv[nopt][2] >= '0' && argv[nopt][2] <= '9')) ){
00392
00393 int ival , nxyz , isub , ll ;
00394 THD_3dim_dataset * dset ;
00395
00396 ival = argv[nopt][1] - 'a' ;
00397 if( VAR_DEFINED(ival) )
00398 ERROR_exit("Can't define %c symbol twice\n",argv[nopt][1]);
00399
00400 isub = (ids == 2) ? 0 : strtol(argv[nopt]+2,NULL,10) ;
00401 if( isub < 0 )
00402 ERROR_exit("Illegal sub-brick value: %s\n",argv[nopt]) ;
00403
00404 nopt++ ;
00405 if( nopt >= argc )
00406 ERROR_exit("need argument after %s\n",argv[nopt-1]);
00407
00408
00409
00410 ll = strlen(argv[nopt]) ;
00411 if( ll >= 4 &&
00412 strstr(argv[nopt],"1D") != NULL &&
00413 argv[nopt][1] == ':' &&
00414 (argv[nopt][0] == 'I' || argv[nopt][0] == 'i' ||
00415 argv[nopt][0] == 'J' || argv[nopt][0] == 'j' ||
00416 argv[nopt][0] == 'K' || argv[nopt][0] == 'k' ) ){
00417
00418 ll = IJKAR_reader( ival , argv[nopt]+2 ) ;
00419 if( ll == 0 ){
00420 switch( argv[nopt][0] ){
00421 case 'I': case 'i': IJKAR_dcod[ival] = 8 ; break ;
00422 case 'J': case 'j': IJKAR_dcod[ival] = 9 ; break ;
00423 case 'K': case 'k': IJKAR_dcod[ival] = 10 ; break ;
00424 }
00425 nopt++ ; goto DSET_DONE ;
00426 }
00427 }
00428
00429
00430
00431 ll = strlen(argv[nopt]) ;
00432 if( ll >= 4 && ( strstr(argv[nopt],".1D") != NULL ||
00433 strstr(argv[nopt],"1D:") != NULL ) ){
00434
00435 ll = TS_reader( ival , argv[nopt] ) ;
00436 if( ll == 0 ){ nopt++ ; goto DSET_DONE ; }
00437
00438
00439 }
00440
00441
00442
00443
00444 if( (argv[nopt][0] >= 'a' && argv[nopt][0] <= 'z') &&
00445 ( (ll >= 3 && argv[nopt][1] == '[') ||
00446 (ll == 3 &&
00447 (argv[nopt][1] == '+' || argv[nopt][1] == '-'))
00448 ) ){
00449
00450 int jds = argv[nopt][0] - 'a' ;
00451 int * ijkl ;
00452
00453
00454
00455 if( ids > 2 )
00456 ERROR_exit("Can't combine %s with differential subscripting %s\n",
00457 argv[nopt-1],argv[nopt]) ;
00458 if( CALC_dset[jds] == NULL )
00459 ERROR_exit("Must define dataset %c before using it in %s\n",
00460 argv[nopt][0] , argv[nopt] ) ;
00461
00462
00463
00464 if( argv[nopt][1] == '[' ){
00465 MCW_intlist_allow_negative(1) ;
00466 ijkl = MCW_get_intlist( 9999 , argv[nopt]+1 ) ;
00467 MCW_intlist_allow_negative(0) ;
00468 if( ijkl == NULL || ijkl[0] != 4 )
00469 ERROR_exit("Illegal differential subscripting %s\n",
00470 argv[nopt] ) ;
00471 } else {
00472 ijkl = (int *) malloc( sizeof(int) * 5 ) ;
00473 ijkl[1] = ijkl[2] = ijkl[3] = ijkl[4] = 0 ;
00474 switch( argv[nopt][2] ){
00475 default:
00476 ERROR_exit("Bad differential subscripting %s\n",argv[nopt]);
00477
00478 case 'i': ijkl[1] = (argv[nopt][1]=='+') ? 1 : -1 ; break ;
00479 case 'j': ijkl[2] = (argv[nopt][1]=='+') ? 1 : -1 ; break ;
00480 case 'k': ijkl[3] = (argv[nopt][1]=='+') ? 1 : -1 ; break ;
00481 case 'l': ijkl[4] = (argv[nopt][1]=='+') ? 1 : -1 ; break ;
00482 }
00483 }
00484
00485
00486
00487 if( ijkl[1]==0 && ijkl[2]==0 && ijkl[3]==0 && ijkl[4]==0 )
00488 WARNING_message("differential subscript %s is all zero\n",argv[nopt]);
00489
00490 if( ntime[jds] == 1 && ijkl[4] != 0 ){
00491 WARNING_message(
00492 "differential subscript %s has nonzero time\n"
00493 " + shift on base dataset with 1 sub-brick!\n"
00494 " + Setting time shift to 0.\n" ,
00495 argv[nopt] ) ;
00496 ijkl[4] = 0 ;
00497 }
00498
00499
00500
00501 CALC_dshift [ival] = jds ;
00502 CALC_dshift_i[ival] = ijkl[1] ;
00503 CALC_dshift_j[ival] = ijkl[2] ;
00504 CALC_dshift_k[ival] = ijkl[3] ;
00505 CALC_dshift_l[ival] = ijkl[4] ;
00506
00507 CALC_dshift_mode[ival] = CALC_dshift_mode_current ;
00508
00509 CALC_has_timeshift = CALC_has_timeshift || (ijkl[4] != 0) ;
00510
00511
00512
00513 free(ijkl) ; nopt++ ; goto DSET_DONE ;
00514
00515 }
00516
00517
00518
00519 #ifndef ALLOW_SUBV
00520 dset = THD_open_one_dataset( argv[nopt++] ) ;
00521 if( dset == NULL )
00522 ERROR_exit("can't open dataset %s\n",argv[nopt-1]) ;
00523 if( isub >= DSET_NVALS(dset) )
00524 ERROR_exit("dataset %s only has %d sub-bricks\n",
00525 argv[nopt-1],DSET_NVALS(dset)) ;
00526 #else
00527 { char dname[512] ;
00528
00529 if( ids > 2 ){
00530 if( strstr(argv[nopt],"[") != NULL ){
00531 ERROR_exit(
00532 "Illegal combination of sub-brick specifiers: "
00533 "%s %s\n" ,
00534 argv[nopt-1] , argv[nopt] ) ;
00535 }
00536 sprintf(dname,"%s[%d]",argv[nopt++],isub) ;
00537 isub = 0 ;
00538 } else {
00539 strcpy(dname,argv[nopt++]) ;
00540 }
00541 dset = THD_open_dataset( dname ) ;
00542 if( dset == NULL )
00543 ERROR_exit("can't open dataset %s\n",dname) ;
00544 }
00545 #endif
00546
00547
00548
00549 #ifdef ALLOW_BUCKETS
00550 ntime[ival] = DSET_NVALS(dset) ;
00551 #else
00552 ntime[ival] = DSET_NUM_TIMES(dset);
00553 #endif
00554 if ( ids > 2 ) ntime[ival] = 1 ;
00555 ntime_max = MAX( ntime_max, ntime[ival] );
00556
00557 nxyz = dset->daxes->nxx * dset->daxes->nyy * dset->daxes->nzz ;
00558 if( CALC_nvox < 0 ){
00559 CALC_nvox = nxyz ;
00560 } else if( nxyz != CALC_nvox ){
00561 ERROR_exit("dataset %s differs in size from others\n",argv[nopt-1]);
00562 }
00563
00564 if( !DSET_datum_constant(dset) ){
00565 float *far ;
00566
00567 WARNING_message("dataset %s has sub-bricks with different types\n"
00568 " + ==> converting all sub-bricks to floats\n",
00569 argv[nopt-1]);
00570
00571 DSET_mallocize(dset) ; DSET_load(dset) ;
00572 if( ! DSET_LOADED(dset) )
00573 ERROR_exit("can't load %s from disk!\n",argv[nopt-1]);
00574
00575 for( ii=0 ; ii < ntime[ival] ; ii++ ){
00576 if( DSET_BRICK_TYPE(dset,ii) != MRI_float ){
00577 far = calloc( sizeof(float) , nxyz ) ;
00578 if( far == NULL )
00579 ERROR_exit("can't malloc space for conversion\n");
00580 EDIT_coerce_scale_type( nxyz , DSET_BRICK_FACTOR(dset,ii) ,
00581 DSET_BRICK_TYPE(dset,ii), DSET_ARRAY(dset,ii),
00582 MRI_float , far ) ;
00583 EDIT_substitute_brick( dset , ii , MRI_float , far ) ;
00584 DSET_BRICK_FACTOR(dset,ii) = 0.0 ;
00585 }
00586 }
00587 }
00588
00589 CALC_type[ival] = DSET_BRICK_TYPE(dset,isub) ;
00590 CALC_dset[ival] = dset ;
00591
00592
00593
00594
00595
00596 CALC_ffac[ival] = (float *) malloc( sizeof(float) * ntime[ival] ) ;
00597 if ( ntime[ival] == 1 ) {
00598 CALC_ffac[ival][0] = DSET_BRICK_FACTOR( dset , isub) ;
00599 if (CALC_ffac[ival][0] == 0.0 ) CALC_ffac[ival][0] = 1.0 ;
00600 if( CALC_ffac[ival][0] != 1.0 ) CALC_noffac[ival] = 0 ;
00601 } else {
00602 for (ii = 0 ; ii < ntime[ival] ; ii ++ ) {
00603 CALC_ffac[ival][ii] = DSET_BRICK_FACTOR(dset, ii) ;
00604 if (CALC_ffac[ival][ii] == 0.0 ) CALC_ffac[ival][ii] = 1.0;
00605 if( CALC_ffac[ival][ii] != 1.0 ) CALC_noffac[ival] = 0 ;
00606 }
00607 }
00608
00609
00610
00611 if( CALC_verbose ){
00612 int iv , nb ;
00613 for( iv=nb=0 ; iv < DSET_NVALS(dset) ; iv++ )
00614 nb += DSET_BRICK_BYTES(dset,iv) ;
00615 INFO_message("Reading dataset %s (%d bytes)\n",argv[nopt-1],nb);
00616 }
00617
00618 if( ! DSET_LOADED(dset) ){
00619 THD_load_datablock( dset->dblk ) ;
00620 if( ! DSET_LOADED(dset) )
00621 ERROR_exit("Can't read data brick for dataset %s\n",argv[nopt-1]) ;
00622 }
00623
00624
00625 switch (CALC_type[ival]) {
00626 case MRI_short:
00627 CALC_short[ival] = (short **) malloc( sizeof(short *) * ntime[ival] ) ;
00628 if (ntime[ival] == 1 )
00629 CALC_short[ival][0] = (short *) DSET_ARRAY(dset, isub) ;
00630 else
00631 for (ii=0; ii < ntime[ival]; ii++)
00632 CALC_short[ival][ii] = (short *) DSET_ARRAY(dset, ii);
00633 break;
00634
00635 case MRI_float:
00636 CALC_float[ival] = (float **) malloc( sizeof(float *) * ntime[ival] ) ;
00637 if (ntime[ival] == 1 )
00638 CALC_float[ival][0] = (float *) DSET_ARRAY(dset, isub) ;
00639 else
00640 for (ii=0; ii < ntime[ival]; ii++)
00641 CALC_float[ival][ii] = (float *) DSET_ARRAY(dset, ii);
00642 break;
00643
00644 case MRI_byte:
00645 CALC_byte[ival] = (byte **) malloc( sizeof(byte *) * ntime[ival] ) ;
00646 if (ntime[ival] == 1 )
00647 CALC_byte[ival][0] = (byte *) DSET_ARRAY(dset, isub) ;
00648 else
00649 for (ii=0; ii < ntime[ival]; ii++)
00650 CALC_byte[ival][ii] = (byte *) DSET_ARRAY(dset, ii);
00651 break;
00652
00653 case MRI_rgb:
00654 CALC_byte[ival] = (byte **) malloc( sizeof(byte *) * ntime[ival] ) ;
00655 if (ntime[ival] == 1 )
00656 CALC_byte[ival][0] = (byte *) DSET_ARRAY(dset, isub) ;
00657 else
00658 for (ii=0; ii < ntime[ival]; ii++)
00659 CALC_byte[ival][ii] = (byte *) DSET_ARRAY(dset, ii);
00660 break ;
00661
00662 default:
00663 ERROR_exit("Dataset %s has illegal data type: %s\n" ,
00664 argv[nopt-1] , MRI_type_name[CALC_type[ival]] ) ;
00665
00666 }
00667 if( CALC_datum < 0 && CALC_type[ival] != MRI_rgb ) CALC_datum = CALC_type[ival] ;
00668
00669 DSET_DONE: continue;
00670
00671 }
00672
00673 ERROR_exit("Unknown option: %s\n",argv[nopt]) ;
00674
00675 }
00676
00677
00678
00679
00680 if( nopt < argc )
00681 ERROR_exit("Extra command line arguments puzzle me! argv[%d]=%s ...\n",nopt,argv[nopt]) ;
00682
00683 for( ids=0 ; ids < 26 ; ids++ ) if( CALC_dset[ids] != NULL ) break ;
00684 if( ids == 26 )
00685 ERROR_exit("No actual input datasets given!\n") ;
00686
00687
00688
00689 for( ii=0 ; ii < 26 ; ii++ ){
00690 if( IJKAR_flim[ii] != NULL ){
00691 int siz ;
00692 switch( IJKAR_dcod[ii] ){
00693 case 8: siz = DSET_NX(CALC_dset[ids]) ; break ;
00694 case 9: siz = DSET_NY(CALC_dset[ids]) ; break ;
00695 case 10: siz = DSET_NZ(CALC_dset[ids]) ; break ;
00696 }
00697 if( IJKAR_flim[ii]->nx != siz )
00698 ERROR_message("dimension mismatch between '-%c' and '%-c'\n", 'a'+ii , 'a'+ids ) ;
00699 }
00700 }
00701
00702 if( CALC_code == NULL ) ERROR_exit("No expression given!\n") ;
00703
00704 if( CALC_histpar >= 0 && CALC_dset[CALC_histpar] == NULL ){
00705 WARNING_message("-histpar dataset not defined!\n") ;
00706 CALC_histpar = -1 ;
00707 }
00708
00709 for (ids=0; ids < 26; ids ++)
00710 if (ntime[ids] > 1 && ntime[ids] != ntime_max ) {
00711 #ifdef ALLOW_BUCKETS
00712 ERROR_exit("Multi-brick datasets don't match!\n") ;
00713 #else
00714 ERROR_exit("3D+time datasets don't match!\n") ;
00715 #endif
00716 }
00717
00718
00719
00720
00721
00722 if( ntime_max == 1 && TS_nmax > 0 ){
00723 ntime_max = TS_nmax ;
00724 TS_make = 1 ;
00725 INFO_message(
00726 "Calculating 3D+time[%d]"
00727 " dataset from 3D datasets and time series, with dt=%g s\n" ,
00728 ntime_max , TS_dt ) ;
00729 }
00730
00731 if( CALC_taxis_num > 0 ){
00732 if( ntime_max > 1 ){
00733 WARNING_message("-taxis %d overriden by dataset input(s)\n",
00734 CALC_taxis_num) ;
00735 } else {
00736 ntime_max = CALC_taxis_num ;
00737 TS_make = 1 ;
00738 INFO_message("Calculating 3D+time[%d]"
00739 " dataset from 3D datasets and -taxis with dt=%g s\n" ,
00740 ntime_max , TS_dt ) ;
00741 }
00742 }
00743
00744
00745
00746
00747 for (ids=0; ids < 26; ids ++){
00748 if( VAR_DEFINED(ids) && !CALC_has_sym[ids] )
00749 WARNING_message("input '%c' is not used in the expression\n" ,
00750 abet[ids] ) ;
00751
00752 else if( !VAR_DEFINED(ids) && CALC_has_sym[ids] ){
00753
00754 if( ((1<<ids) & PREDEFINED_MASK) == 0 ){
00755 WARNING_message( "symbol %c is used but not defined\n" , abet[ids] ) ;
00756 } else {
00757 CALC_has_predefined++ ;
00758 INFO_message("Symbol %c using predefined value\n",abet[ids] ) ;
00759 if( ids >= 23 ) CALC_has_xyz = 1 ;
00760 }
00761 }
00762 }
00763
00764 return ;
00765 }
00766
00767
00768
00769 void CALC_Syntax(void)
00770 {
00771 printf(
00772 "Program: 3dcalc \n"
00773 "Author: RW Cox et al \n"
00774 " \n"
00775 "3dcalc - AFNI's calculator program \n"
00776 " \n"
00777 " This program does voxel-by-voxel arithmetic on 3D datasets \n"
00778 " (limited to inter-voxel computation). \n"
00779 " \n"
00780 " The program assumes that the voxel-by-voxel computations are being \n"
00781 " performed on datasets that occupy the same space and have the same \n"
00782 " orientations. \n"
00783 " \n"
00784 "------------------------------------------------------------------------\n"
00785 "Usage: \n"
00786 "----- \n"
00787 " 3dcalc -a dsetA [-b dsetB...] \\ \n"
00788 " -expr EXPRESSION \\ \n"
00789 " [options] \n"
00790 " \n"
00791 "Examples: \n"
00792 "-------- \n"
00793 "1. Average datasets together, on a voxel-by-voxel basis: \n"
00794 " \n"
00795 " 3dcalc -a fred+tlrc -b ethel+tlrc -c lucy+tlrc \\ \n"
00796 " -expr '(a+b+c)/3' -prefix subjects_mean \n"
00797 " \n"
00798 "2. Perform arithmetic calculations between the sub-bricks of a single \n"
00799 " dataset by noting the sub-brick number on the command line: \n"
00800 " \n"
00801 " 3dcalc -a 'func+orig[2]' -b 'func+orig[4]' -expr 'sqrt(a*b)' \n"
00802 " \n"
00803 "3. Create a simple mask that consists only of values in sub-brick #0 \n"
00804 " that are greater than 3.14159: \n"
00805 " \n"
00806 " 3dcalc -a 'func+orig[0]' -expr 'ispositive(a-3.14159)' \\ \n"
00807 " -prefix mask \n"
00808 " \n"
00809 "4. Normalize subjects' time series datasets to percent change values in \n"
00810 " preparation for group analysis: \n"
00811 " \n"
00812 " Voxel-by-voxel, the example below divides each intensity value in \n"
00813 " the time series (epi_r1+orig) with the voxel's mean value (mean+orig)\n"
00814 " to get a percent change value. The 'ispositive' command will ignore \n"
00815 " voxels with mean values less than 167 (i.e., they are labeled as \n"
00816 " 'zero' in the output file 'percent_change+orig') and are most likely \n"
00817 " background/noncortical voxels. \n"
00818 " \n"
00819 " 3dcalc -a epi_run1+orig -b mean+orig \\ \n"
00820 " -expr '100 * a/b * ispositive(b-167)' -prefix percent_chng \n"
00821 " \n"
00822 "5. Create a compound mask from a statistical dataset, where 3 stimuli \n"
00823 " show activation. \n"
00824 " NOTE: 'step' and 'ispositive' are identical expressions that can \n"
00825 " be used interchangeably: \n"
00826 " \n"
00827 " 3dcalc -a 'func+orig[12]' -b 'func+orig[15]' -c 'func+orig[18]' \\ \n"
00828 " -expr 'step(a-4.2)*step(b-2.9)*step(c-3.1)' \\ \n"
00829 " -prefix compound_mask \n"
00830 " \n"
00831 "6. Same as example #5, but this time create a mask of 8 different values\n"
00832 " showing all combinations of activations (i.e., not only where \n"
00833 " everything is active, but also each stimulus individually, and all \n"
00834 " combinations). The output mask dataset labels voxel values as such: \n"
00835 " 0 = none active 1 = A only active 2 = B only active \n"
00836 " 3 = A and B only 4 = C only active 5 = A and C only \n"
00837 " 6 = B and C only 7 = all A, B, and C active \n"
00838 " \n"
00839 " 3dcalc -a 'func+orig[12]' -b 'func+orig[15]' -c 'func+orig[18]' \\ \n"
00840 " -expr 'step(a-4.2)+2*step(b-2.9)+4*step(c-3.1)' \\ \n"
00841 " -prefix mask_8 \n"
00842 " \n"
00843 "7. Create a region-of-interest mask comprised of a 3-dimensional sphere.\n"
00844 " Values within the ROI sphere will be labeled as '1' while values \n"
00845 " outside the mask will be labeled as '0'. Statistical analyses can \n"
00846 " then be done on the voxels within the ROI sphere. \n"
00847 " \n"
00848 " The example below puts a solid ball (sphere) of radius 3=sqrt(9) \n"
00849 " about the point with coordinates (x,y,z)=(20,30,70): \n"
00850 " \n"
00851 " 3dcalc -a anat+tlrc \\\n"
00852 " -expr 'step((9-(x-20)*(x-20)-(y-30)*(y-30)-(z-70)*(z-70))'\\\n"
00853 " -prefix ball \n"
00854 " \n"
00855 " 8. Some datsets are 'short' (16 bit) integers with a scalar attached, \n"
00856 " which allow them to be smaller than float datasets and to contain \n"
00857 " fractional values. \n"
00858 " \n"
00859 " Dataset 'a' is always used as a template for the output dataset. For\n"
00860 " the examples below, assume that datasets d1+orig and d2+orig consist\n"
00861 " of small integers. \n"
00862 " \n"
00863 " a) When dividing 'a' by 'b', the result should be scaled, so that a \n"
00864 " value of 2.4 is not truncated to '2'. To avoid this truncation, \n"
00865 " force scaling with the -fscale option: \n"
00866 " \n"
00867 " 3dcalc -a d1+orig -b d2+orig -expr 'a/b' -prefix quot -fscale \n"
00868 " \n"
00869 " b) If it is preferable that the result is of type 'float', then set \n"
00870 " the output data type (datum) to float: \n"
00871 " \n"
00872 " 3dcalc -a d1+orig -b d2+orig -expr 'a/b' -prefix quot \\ \n"
00873 " -datum float \n"
00874 " \n"
00875 " c) Perhaps an integral division is desired, so that 9/4=2, not 2.24.\n"
00876 " Force the results not to be scaled (opposite of example 8b) using\n"
00877 " the -nscale option: \n"
00878 " \n"
00879 " 3dcalc -a d1+orig -b d2+orig -expr 'a/b' -prefix quot -nscale \n"
00880 " \n"
00881 "------------------------------------------------------------------------\n"
00882 " \n"
00883 "ARGUMENTS for 3dcalc (must be included on command line): \n"
00884 "-------------------- ---- \n"
00885 " \n"
00886 " -a dname = Read dataset 'dname' and call the voxel values 'a' in the\n"
00887 " expression (-expr) that is input below. Up to 24 dnames \n"
00888 " (-a, -b, -c, ... -z) can be included in a single 3dcalc \n"
00889 " calculation/expression. \n"
00890 " ** If some letter name is used in the expression, but \n"
00891 " not present in one of the dataset options here, then \n"
00892 " that variable is set to 0. \n"
00893 " ** If the letter is followed by a number, then that \n"
00894 " number is used to select the sub-brick of the dataset \n"
00895 " which will be used in the calculations. \n"
00896 " E.g., '-b3 dname' specifies that the variable 'b' \n"
00897 " refers to sub-brick '3' of that dataset \n"
00898 " (indexes in AFNI start at 0). \n"
00899 " \n"
00900 " -expr = Apply the expression - within quotes - to the input \n"
00901 " datasets (dnames), one voxel at time, to produce the \n"
00902 " output dataset. \n"
00903 "------------------------------------------------------------------------\n"
00904 ) ;
00905 printf(
00906 " OPTIONS for 3dcalc: \n"
00907 " ------- \n"
00908 " \n"
00909 " -verbose = Makes the program print out various information as it \n"
00910 " progresses. \n"
00911 " \n"
00912 " -datum type= Coerce the output data to be stored as the given type, \n"
00913 " which may be byte, short, or float. \n"
00914 " [default = datum of first input dataset] \n"
00915 " \n"
00916 " -fscale = Force scaling of the output to the maximum integer \n"
00917 " range. This only has effect if the output datum is byte \n"
00918 " or short (either forced or defaulted). This option is \n"
00919 " often necessary to eliminate unpleasant truncation \n"
00920 " artifacts. \n"
00921 " [The default is to scale only if the computed values \n"
00922 " seem to need it -- are all <= 1.0 or there is at \n"
00923 " least one value beyond the integer upper limit.] \n"
00924 " \n"
00925 " ** In earlier versions of 3dcalc, scaling (if used) was \n"
00926 " applied to all sub-bricks equally -- a common scale \n"
00927 " factor was used. This would cause trouble if the \n"
00928 " values in different sub-bricks were in vastly \n"
00929 " different scales. In this version, each sub-brick \n"
00930 " gets its own scale factor. To override this behavior,\n"
00931 " use the '-gscale' option. \n"
00932 " \n"
00933 " -gscale = Same as '-fscale', but also forces each output sub-brick \n"
00934 " to get the same scaling factor. This may be desirable \n"
00935 " for 3D+time datasets, for example. \n"
00936 " \n"
00937 " -nscale = Don't do any scaling on output to byte or short datasets.\n"
00938 " This may be especially useful when operating on mask \n"
00939 " datasets whose output values are only 0's and 1's. \n"
00940 #ifndef ALLOW_SUBV
00941 " ** The type and number of sub-bricks in a dataset can be \n"
00942 " printed out using the '3dinfo' program. \n"
00943 #else
00944 " ** Another way to achieve the effect of '-b3' is described\n"
00945 " below in the dataset 'INPUT' specification section. \n"
00946 #endif
00947 " \n"
00948 " -prefix pname = Use 'pname' for the output dataset prefix name. \n"
00949 " [default='calc'] \n"
00950 " \n"
00951 " -session dir = Use 'dir' for the output dataset session directory. \n"
00952 " [default='./'=current working directory] \n"
00953 " \n"
00954 " -dt tstep = Use 'tstep' as the TR for manufactured 3D+time datasets.\n"
00955 " \n"
00956 " -TR tstep = If not given, defaults to 1 second. \n"
00957 " \n"
00958 " -taxis N = If only 3D datasets are input (no 3D+time or .1D files),\n"
00959 " *OR* then normally only a 3D dataset is calculated. With \n"
00960 " -taxis N:tstep: this option, you can force the creation of a time axis\n"
00961 " of length 'N', optionally using time step 'tstep'. In\n"
00962 " such a case, you will probably want to use the pre- \n"
00963 " defined time variables 't' and/or 'k' in your \n"
00964 " expression, or each resulting sub-brick will be \n"
00965 " identical. For example: \n"
00966 " '-taxis 121:0.1' will produce 121 points in time, \n"
00967 " spaced with TR 0.1. \n"
00968 " \n"
00969 " N.B.: You can also specify the TR using the -dt option. \n"
00970 " N.B.: You can specify 1D input datasets using the \n"
00971 " '1D:n@val,n@val' notation to get a similar effect. \n"
00972 " For example: \n"
00973 " -dt 0.1 -w '1D:121@0' \n"
00974 " will have pretty much the same effect as \n"
00975 " -taxis 121:0.1\n"
00976 " N.B.: For both '-dt' and '-taxis', the 'tstep' value is in \n"
00977 " seconds. You can suffix it with 'ms' to specify that\n"
00978 " the value is in milliseconds instead; e.g., '-dt 2000ms'.\n"
00979 " \n"
00980 " -rgbfac A B C = For RGB input datasets, the 3 channels (r,g,b) are \n"
00981 " collapsed to one for the purposes of 3dcalc, using the\n"
00982 " formula value = A*r + B*g + C*b \n"
00983 " \n"
00984 " The default values are A=0.299 B=0.587 C=0.114, which \n"
00985 " gives the grayscale intensity. To pick out the Green \n"
00986 " channel only, use '-rgbfac 0 1 0', for example. Note \n"
00987 " that each channel in an RGB dataset is a byte in the \n"
00988 " range 0..255. Thus, '-rgbfac 0.001173 0.002302 0.000447'\n"
00989 " will compute the intensity rescaled to the range 0..1.0\n"
00990 " (i.e., 0.001173=0.299/255, etc.) \n"
00991 " \n"
00992 "------------------------------------------------------------------------\n"
00993 "DATASET TYPES: \n"
00994 "------------- \n"
00995 " \n"
00996 " The most common AFNI dataset types are 'byte', 'short', and 'float'. \n"
00997 " \n"
00998 " A byte value is an 8-bit signed integer (0..255), a short value ia a \n"
00999 " 16-bit signed integer (-32768..32767), and a float value is a 32-bit \n"
01000 " real number. A byte value has almost 3 decimals of accuracy, a short \n"
01001 " has almost 5, and a float has approximately 7 (from a 23+1 bit \n"
01002 " mantissa). \n"
01003 " \n"
01004 " Datasets can also have a scalar attached to each sub-brick. The main \n"
01005 " use of this is allowing a short type dataset to take on non-integral \n"
01006 " values, while being half the size of a float dataset. \n"
01007 " \n"
01008 " As an example, consider a short dataset with a scalar of 0.0001. This \n"
01009 " could represent values between -32.768 and +32.767, at a resolution of \n"
01010 " 0.001. One could represnt the difference between 4.916 and 4.917, for \n"
01011 " instance, but not 4.9165. Each number has 15 bits of accuracy, plus a \n"
01012 " sign bit, which gives 4-5 decimal places of accuracy. If this is not \n"
01013 " enough, then it makes sense to use the larger type, float. \n"
01014 " \n"
01015 "------------------------------------------------------------------------\n"
01016 "3D+TIME DATASETS: \n"
01017 "---------------- \n"
01018 " \n"
01019 " This version of 3dcalc can operate on 3D+time datasets. Each input \n"
01020 " dataset will be in one of these conditions: \n"
01021 " \n"
01022 " (A) Is a regular 3D (no time) dataset; or \n"
01023 " (B) Is a 3D+time dataset with a sub-brick index specified ('-b3'); or\n"
01024 " (C) Is a 3D+time dataset with no sub-brick index specified ('-b'). \n"
01025 " \n"
01026 " If there is at least one case (C) dataset, then the output dataset will\n"
01027 " also be 3D+time; otherwise it will be a 3D dataset with one sub-brick. \n"
01028 " When producing a 3D+time dataset, datasets in case (A) or (B) will be \n"
01029 " treated as if the particular brick being used has the same value at each\n"
01030 " point in time. \n"
01031 " \n"
01032 #ifdef ALLOW_BUCKETS
01033 " Multi-brick 'bucket' datasets may also be used. Note that if multi-brick\n"
01034 " (bucket or 3D+time) datasets are used, the lowest letter dataset will \n"
01035 " serve as the template for the output; that is, '-b fred+tlrc' takes \n"
01036 " precedence over '-c wilma+tlrc'. (The program 3drefit can be used to \n"
01037 " alter the .HEAD parameters of the output dataset, if desired.) \n"
01038 #endif
01039
01040 #ifdef ALLOW_SUBV
01041 " \n"
01042 "------------------------------------------------------------------------\n"
01043 MASTER_HELP_STRING
01044 " \n"
01045 "** WARNING: you cannot combine sub-brick selection of the form \n"
01046 " -b3 bambam+orig (the old method) \n"
01047 " with sub-brick selection of the form \n"
01048 " -b 'bambam+orig[3]' (the new method) \n"
01049 " If you try, the Doom of Mandos will fall upon you! \n"
01050 #endif
01051 " \n"
01052 "------------------------------------------------------------------------\n"
01053 "1D TIME SERIES: \n"
01054 "-------------- \n"
01055 " \n"
01056 " You can also input a '*.1D' time series file in place of a dataset. \n"
01057 " In this case, the value at each spatial voxel at time index n will be \n"
01058 " the same, and will be the n-th value from the time series file. \n"
01059 " At least one true dataset must be input. If all the input datasets \n"
01060 " are 3D (single sub-brick) or are single sub-bricks from multi-brick \n"
01061 " datasets, then the output will be a 'manufactured' 3D+time dataset. \n"
01062 " \n"
01063 " For example, suppose that 'a3D+orig' is a 3D dataset: \n"
01064 " \n"
01065 " 3dcalc -a a3D+orig -b b.1D -expr \"a*b\" \n"
01066 " \n"
01067 " The output dataset will 3D+time with the value at (x,y,z,t) being \n"
01068 " computed by a3D(x,y,z)*b(t). The TR for this dataset will be set \n"
01069 " to 'tstep' seconds -- this could be altered later with program 3drefit.\n"
01070 " Another method to set up the correct timing would be to input an \n"
01071 " unused 3D+time dataset -- 3dcalc will then copy that dataset's time \n"
01072 " information, but simply do not use that dataset's letter in -expr. \n"
01073 " \n"
01074 " If the *.1D file has multiple columns, only the first read will be \n"
01075 " used in this program. You can select a column to be the first by \n"
01076 " using a sub-vector selection of the form 'b.1D[3]', which will \n"
01077 " choose the 4th column (since counting starts at 0). \n"
01078 " \n"
01079 " '{...}' row selectors can also be used - see the output of '1dcat -help'\n"
01080 " for more details on these. Note that if multiple timeseries or 3D+time\n"
01081 " or 3D bucket datasets are input, they must all have the same number of \n"
01082 " points along the 'time' dimension. \n"
01083 " \n"
01084 "------------------------------------------------------------------------\n"
01085 "'1D:' INPUT: \n"
01086 "----------- \n"
01087 " \n"
01088 " You can input a 1D time series 'dataset' directly on the command line, \n"
01089 " without an external file. The 'filename for such input takes the \n"
01090 " general format \n"
01091 " \n"
01092 " '1D:n_1@val_1,n_2@val_2,n_3@val_3,...' \n"
01093 " \n"
01094 " where each 'n_i' is an integer and each 'val_i' is a float. For \n"
01095 " example \n"
01096 " \n"
01097 " -a '1D:5@0,10@1,5@0,10@1,5@0' \n"
01098 " \n"
01099 " specifies that variable 'a' be assigned to a 1D time series of 35, \n"
01100 " alternating in blocks between values 0 and value 1. \n"
01101 " \n"
01102 "------------------------------------------------------------------------\n"
01103 "'I:*.1D' and 'J:*.1D' and 'K:*.1D' INPUT: \n"
01104 "---------------------------------------- \n"
01105 " \n"
01106 " You can input a 1D time series 'dataset' to be defined as spatially \n"
01107 " dependent instead of time dependent using a syntax like: \n"
01108 " \n"
01109 " -c I:fred.1D \n"
01110 " \n"
01111 " This indicates that the n-th value from file fred.1D is to be associated\n"
01112 " with the spatial voxel index i=n (respectively j=n and k=n for 'J: and \n"
01113 " K: input dataset names). This technique can be useful if you want to \n"
01114 " scale each slice by a fixed constant; for example: \n"
01115 " \n"
01116 " -a dset+orig -b K:slicefactor.1D -expr 'a*b' \n"
01117 " \n"
01118 " In this example, the '-b' value only varies in the k-index spatial \n"
01119 " direction. \n"
01120 " \n"
01121 "------------------------------------------------------------------------\n"
01122 "COORDINATES and PREDEFINED VALUES: \n"
01123 "--------------------------------- \n"
01124 " \n"
01125 " If you don't use '-x', '-y', or '-z' for a dataset, then the voxel \n"
01126 " spatial coordinates will be loaded into those variables. For example, \n"
01127 " the expression 'a*step(x*x+y*y+z*z-100)' will zero out all the voxels \n"
01128 " inside a 10 mm radius of the origin x=y=z=0. \n"
01129 " \n"
01130 " Similarly, the '-t' value, if not otherwise used by a dataset or *.1D \n"
01131 " input, will be loaded with the voxel time coordinate, as determined \n"
01132 " from the header file created for the OUTPUT. Please note that the units\n"
01133 " of this are variable; they might be in milliseconds, seconds, or Hertz.\n"
01134 " In addition, slices of the dataset might be offset in time from one \n"
01135 " another, and this is allowed for in the computation of 't'. Use program\n"
01136 " 3dinfo to find out the structure of your datasets, if you are not sure.\n"
01137 " If no input datasets are 3D+time, then the effective value of TR is \n"
01138 " tstep in the output dataset, with t=0 at the first sub-brick. \n"
01139 " \n"
01140 " Similarly, the '-i', '-j', and '-k' values, if not otherwise used, \n"
01141 " will be loaded with the voxel spatial index coordinates. The '-l' \n"
01142 " (letter 'ell') value will be loaded with the temporal index coordinate.\n"
01143 " \n"
01144 " Otherwise undefined letters will be set to zero. In the future, \n"
01145 " new default values for other letters may be added. \n"
01146 " \n"
01147 " NOTE WELL: By default, the coordinate order of (x,y,z) is the order in \n"
01148 " ********* which the data array is stored on disk; this order is output\n"
01149 " by 3dinfo. The options below control can change this order:\n"
01150 " \n"
01151 " -dicom }= Sets the coordinates to appear in DICOM standard (RAI) order,\n"
01152 " -RAI }= (the AFNI standard), so that -x=Right, -y=Anterior , -z=Inferior,\n"
01153 " +x=Left , +y=Posterior, +z=Superior.\n"
01154 " \n"
01155 " -SPM }= Sets the coordinates to appear in SPM (LPI) order, \n"
01156 " -LPI }= so that -x=Left , -y=Posterior, -z=Inferior,\n"
01157 " +x=Right, +y=Anterior , +z=Superior.\n"
01158 " \n"
01159 "------------------------------------------------------------------------\n"
01160 "DIFFERENTIAL SUBSCRIPTS [22 Nov 1999]: \n"
01161 "----------------------- \n"
01162 " \n"
01163 " Normal calculations with 3dcalc are strictly on a per-voxel basis:\n"
01164 " there is no 'cross-talk' between spatial or temporal locations.\n"
01165 " The differential subscript feature allows you to specify variables\n"
01166 " that refer to different locations, relative to the base voxel.\n"
01167 " For example,\n"
01168 " -a fred+orig -b 'a[1,0,0,0]' -c 'a[0,-1,0,0]' -d 'a[0,0,2,0]'\n"
01169 " means: symbol 'a' refers to a voxel in dataset fred+orig,\n"
01170 " symbol 'b' refers to the following voxel in the x-direction,\n"
01171 " symbol 'c' refers to the previous voxel in the y-direction\n"
01172 " symbol 'd' refers to the 2nd following voxel in the z-direction\n"
01173 "\n"
01174 " To use this feature, you must define the base dataset (e.g., 'a')\n"
01175 " first. Then the differentially subscripted symbols are defined\n"
01176 " using the base dataset symbol followed by 4 integer subscripts,\n"
01177 " which are the shifts in the x-, y-, z-, and t- (or sub-brick index)\n"
01178 " directions. For example,\n"
01179 "\n"
01180 " -a fred+orig -b 'a[0,0,0,1]' -c 'a[0,0,0,-1]' -expr 'median(a,b,c)'\n"
01181 "\n"
01182 " will produce a temporal median smoothing of a 3D+time dataset (this\n"
01183 " can be done more efficiently with program 3dTsmooth).\n"
01184 "\n"
01185 " Note that the physical directions of the x-, y-, and z-axes depend\n"
01186 " on how the dataset was acquired or constructed. See the output of\n"
01187 " program 3dinfo to determine what direction corresponds to what axis.\n"
01188 "\n"
01189 " For convenience, the following abbreviations may be used in place of\n"
01190 " some common subscript combinations:\n"
01191 "\n"
01192 " [1,0,0,0] == +i [-1, 0, 0, 0] == -i\n"
01193 " [0,1,0,0] == +j [ 0,-1, 0, 0] == -j\n"
01194 " [0,0,1,0] == +k [ 0, 0,-1, 0] == -k\n"
01195 " [0,0,0,1] == +l [ 0, 0, 0,-1] == -l\n"
01196 "\n"
01197 " The median smoothing example can thus be abbreviated as\n"
01198 "\n"
01199 " -a fred+orig -b a+l -c a-l -expr 'median(a,b,c)'\n"
01200 "\n"
01201 " When a shift calls for a voxel that is outside of the dataset range,\n"
01202 " one of three things can happen:\n"
01203 "\n"
01204 " STOP => shifting stops at the edge of the dataset\n"
01205 " WRAP => shifting wraps back to the opposite edge of the dataset\n"
01206 " ZERO => the voxel value is returned as zero\n"
01207 "\n"
01208 " Which one applies depends on the setting of the shifting mode at the\n"
01209 " time the symbol using differential subscripting is defined. The mode\n"
01210 " is set by one of the switches '-dsSTOP', '-dsWRAP', or '-dsZERO'. The\n"
01211 " default mode is STOP. Suppose that a dataset has range 0..99 in the\n"
01212 " x-direction. Then when voxel 101 is called for, the value returned is\n"
01213 "\n"
01214 " STOP => value from voxel 99 [didn't shift past edge of dataset]\n"
01215 " WRAP => value from voxel 1 [wrapped back through opposite edge]\n"
01216 " ZERO => the number 0.0 \n"
01217 "\n"
01218 " You can set the shifting mode more than once - the most recent setting\n"
01219 " on the command line applies when a differential subscript symbol is\n"
01220 " encountered.\n"
01221 "\n"
01222 "------------------------------------------------------------------------\n"
01223 "PROBLEMS:\n"
01224 "-------- \n"
01225 "\n"
01226 " * Complex-valued datasets cannot be processed.\n"
01227 " * This program is not very efficient (but is faster than it once was).\n"
01228 " * Differential subscripts slow the program down even more.\n"
01229 "\n"
01230 "------------------------------------------------------------------------\n"
01231 "EXPRESSIONS:\n"
01232 "----------- \n"
01233 "\n"
01234 " Arithmetic expressions are allowed, using + - * / ** and parentheses.\n"
01235 " As noted above, datasets are referred to by single letter variable names.\n"
01236 " At this time, C relational, boolean, and conditional expressions are\n"
01237 " NOT implemented. Built in functions include:\n"
01238 "\n"
01239 " sin , cos , tan , asin , acos , atan , atan2, \n"
01240 " sinh , cosh , tanh , asinh , acosh , atanh , exp , \n"
01241 " log , log10, abs , int , sqrt , max , min , \n"
01242 " J0 , J1 , Y0 , Y1 , erf , erfc , qginv, qg , \n"
01243 " rect , step , astep, bool , and , or , mofn , \n"
01244 " sind , cosd , tand , median, lmode , hmode , mad , \n"
01245 " gran , uran , iran , eran , lran , orstat, \n"
01246 " mean , stdev, sem , Pleg\n"
01247 "\n"
01248 " where:\n"
01249 " * qg(x) = reversed cdf of a standard normal distribution\n"
01250 " * qginv(x) = inverse function to qg\n"
01251 " * min, max, atan2 each take 2 arguments ONLY\n"
01252 " * J0, J1, Y0, Y1 are Bessel functions (see Watson)\n"
01253 " * Pleg(m,x) is the m'th Legendre polynomial evaluated at x\n"
01254 " * erf, erfc are the error and complementary error functions\n"
01255 " * sind, cosd, tand take arguments in degrees (vs. radians)\n"
01256 " * median(a,b,c,...) computes the median of its arguments\n"
01257 " * mad(a,b,c,...) computes the MAD of its arguments\n"
01258 " * mean(a,b,c,...) computes the mean of its arguments\n"
01259 " * stdev(a,b,c,...) computes the standard deviation of its arguments\n"
01260 " * sem(a,b,c,...) computes the standard error of the mean of its arguments,\n"
01261 " where sem(n arguments) = stdev(same)/sqrt(n)\n"
01262 " * orstat(n,a,b,c,...) computes the n-th order statistic of\n"
01263 " {a,b,c,...} - that is, the n-th value in size, starting\n"
01264 " at the bottom (e.g., orstat(1,a,b,c) is the minimum)\n"
01265 " * lmode(a,b,c,...) and hmode(a,b,c,...) compute the mode\n"
01266 " of their arguments - lmode breaks ties by choosing the\n"
01267 " smallest value with the maximal count, hmode breaks ties by\n"
01268 " choosing the largest value with the maximal count\n"
01269 " [median,lmode,hmode take a variable number of arguments]\n"
01270 " * gran(m,s) returns a Gaussian deviate with mean=m, stdev=s\n"
01271 " * uran(r) returns a uniform deviate in the range [0,r]\n"
01272 " * iran(t) returns a random integer in the range [0..t]\n"
01273 " * eran(s) returns an exponentially distributed deviate\n"
01274 " * lran(t) returns a logistically distributed deviate\n"
01275 "\n"
01276 " You may use the symbol 'PI' to refer to the constant of that name.\n"
01277 " This is the only 2 letter symbol defined; all input files are\n"
01278 " referred to by 1 letter symbols. The case of the expression is\n"
01279 " ignored (in fact, it is converted to uppercase as the first step\n"
01280 " in the parsing algorithm).\n"
01281 "\n"
01282 " The following functions are designed to help implement logical\n"
01283 " functions, such as masking of 3D volumes against some criterion:\n"
01284 " step(x) = {1 if x>0 , 0 if x<=0},\n"
01285 " astep(x,y) = {1 if abs(x) > y , 0 otherwise} = step(abs(x)-y)\n"
01286 " rect(x) = {1 if abs(x)<=0.5, 0 if abs(x)>0.5},\n"
01287 " bool(x) = {1 if x != 0.0 , 0 if x == 0.0},\n"
01288 " notzero(x) = bool(x),\n"
01289 " iszero(x) = 1-bool(x) = { 0 if x != 0.0, 1 if x == 0.0 },\n"
01290 " equals(x,y) = 1-bool(x-y) = { 1 if x == y , 0 if x != y },\n"
01291 " ispositive(x) = { 1 if x > 0; 0 if x <= 0 },\n"
01292 " isnegative(x) = { 1 if x < 0; 0 if x >= 0 },\n"
01293 " and(a,b,...,c) = {1 if all arguments are nonzero, 0 if any are zero}\n"
01294 " or(a,b,...,c) = {1 if any arguments are nonzero, 0 if all are zero}\n"
01295 " mofn(m,a,...,c) = {1 if at least 'm' arguments are nonzero, 0 otherwise}\n"
01296 " argmax(a,b,...) = index of largest argument; = 0 if all args are 0\n"
01297 " argnum(a,b,...) = number of nonzero arguments\n"
01298 "\n"
01299 " [These last 5 functions take a variable number of arguments.]\n"
01300 "\n"
01301 " The following 27 new [Mar 1999] functions are used for statistical\n"
01302 " conversions, as in the program 'cdf':\n"
01303 " fico_t2p(t,a,b,c), fico_p2t(p,a,b,c), fico_t2z(t,a,b,c),\n"
01304 " fitt_t2p(t,a) , fitt_p2t(p,a) , fitt_t2z(t,a) ,\n"
01305 " fift_t2p(t,a,b) , fift_p2t(p,a,b) , fift_t2z(t,a,b) ,\n"
01306 " fizt_t2p(t) , fizt_p2t(p) , fizt_t2z(t) ,\n"
01307 " fict_t2p(t,a) , fict_p2t(p,a) , fict_t2z(t,a) ,\n"
01308 " fibt_t2p(t,a,b) , fibt_p2t(p,a,b) , fibt_t2z(t,a,b) ,\n"
01309 " fibn_t2p(t,a,b) , fibn_p2t(p,a,b) , fibn_t2z(t,a,b) ,\n"
01310 " figt_t2p(t,a,b) , figt_p2t(p,a,b) , figt_t2z(t,a,b) ,\n"
01311 " fipt_t2p(t,a) , fipt_p2t(p,a) , fipt_t2z(t,a) .\n"
01312 "\n"
01313 " See the output of 'cdf -help' for documentation on the meanings of\n"
01314 " and arguments to these functions. (After using one of these, you\n"
01315 " may wish to use program '3drefit' to modify the dataset statistical\n"
01316 " auxiliary parameters.)\n"
01317 "\n"
01318 " Computations are carried out in double precision before being\n"
01319 " truncated to the final output 'datum'.\n"
01320 "\n"
01321 " Note that the quotes around the expression are needed so the shell\n"
01322 " doesn't try to expand * characters, or interpret parentheses.\n"
01323 "\n"
01324 " (Try the 'ccalc' program to see how the expression evaluator works.\n"
01325 " The arithmetic parser and evaluator is written in Fortran-77 and\n"
01326 " is derived from a program written long ago by RW Cox to facilitate\n"
01327 " compiling on an array processor hooked up to a VAX. It's a mess,\n"
01328 " but it works - somewhat slowly.)\n"
01329 ) ;
01330 exit(0) ;
01331 }
01332
01333
01334
01335 int main( int argc , char * argv[] )
01336 {
01337 #define VSIZE 1024
01338
01339 double * atoz[26] ;
01340 int ii , ids , jj, kk, kt, ll, jbot, jtop ;
01341 THD_3dim_dataset * new_dset=NULL ;
01342 float ** buf;
01343 double temp[VSIZE];
01344 int nbad ;
01345
01346 THD_ivec3 iv ;
01347 THD_fvec3 fv ;
01348 float xxx[VSIZE], yyy[VSIZE], zzz[VSIZE] ;
01349 int iii,jjj,kkk , nx,nxy ;
01350 THD_dataxes * daxes ;
01351
01352
01353
01354 if( argc < 2 || strncasecmp(argv[1],"-help",4) == 0 ) CALC_Syntax() ;
01355
01356
01357
01358 mainENTRY("3dcalc main"); machdep() ; PRINT_VERSION("3dcalc") ;
01359
01360 { int new_argc ; char ** new_argv ;
01361 addto_args( argc , argv , &new_argc , &new_argv ) ;
01362 if( new_argv != NULL ){ argc = new_argc ; argv = new_argv ; }
01363 }
01364
01365 AFNI_logger("3dcalc",argc,argv) ;
01366
01367 for (ii=0; ii<26; ii++) ntime[ii] = 0 ;
01368
01369 CALC_read_opts( argc , argv ) ;
01370
01371
01372
01373 if( ntime_max == 1 || TS_make == 1 ){
01374 for( ids=0 ; ids < 26 ; ids++ ) if( CALC_dset[ids] != NULL ) break ;
01375 } else {
01376 for( ids=0 ; ids < 26 ; ids++ ) if( CALC_dset[ids] != NULL &&
01377 ntime[ids] > 1 ) break ;
01378 }
01379 if( ids == 26 ) ERROR_exit("Can't find template dataset?!\n") ;
01380
01381 new_dset = EDIT_empty_copy( CALC_dset[ids] ) ;
01382
01383
01384
01385 for( iii=0 ; iii < 26 ; iii++ ){
01386 if( iii != ids &&
01387 CALC_dset[iii] != NULL &&
01388 !EQUIV_DATAXES(new_dset->daxes,CALC_dset[iii]->daxes) )
01389 WARNING_message("dataset '%c'=%s grid mismatch with %s\n",
01390 'a'+iii , DSET_BRIKNAME(CALC_dset[iii]) ,
01391 DSET_BRIKNAME(CALC_dset[ids]) ) ;
01392 }
01393
01394
01395
01396 if( CALC_histpar < 0 ){
01397 for( iii=jjj=0 ; iii < 26 ; iii++ )
01398 if( CALC_dset[iii] != NULL ) jjj++ ;
01399 } else {
01400 ids = CALC_histpar ;
01401 jjj = 1 ;
01402 }
01403
01404 if( jjj == 1 ){
01405 tross_Copy_History( CALC_dset[ids] , new_dset ) ;
01406 } else {
01407 char hbuf[64] ;
01408 tross_Append_History( new_dset ,
01409 "===================================" ) ;
01410 tross_Append_History( new_dset ,
01411 "=== History of inputs to 3dcalc ===" ) ;
01412 for( iii=0 ; iii < 26 ; iii++ ){
01413 if( CALC_dset[iii] != NULL ){
01414 sprintf(hbuf,"=== Input %c:", 'a'+iii ) ;
01415 tross_Append_History( new_dset , hbuf ) ;
01416 tross_Addto_History( CALC_dset[iii] , new_dset ) ;
01417 }
01418 }
01419 tross_Append_History( new_dset ,
01420 "===================================" ) ;
01421 }
01422 tross_Make_History( "3dcalc" , argc,argv , new_dset ) ;
01423
01424 if( CALC_datum < 0 ) CALC_datum = MRI_float ;
01425
01426 EDIT_dset_items( new_dset ,
01427 ADN_prefix , CALC_output_prefix ,
01428 ADN_directory_name , CALC_session ,
01429 ADN_datum_all , CALC_datum ,
01430 ADN_none ) ;
01431
01432 if( DSET_NVALS(new_dset) != ntime_max )
01433 EDIT_dset_items( new_dset , ADN_nvals , ntime_max , ADN_none ) ;
01434
01435
01436
01437
01438 if( TS_make ){
01439 EDIT_dset_items( new_dset ,
01440 ADN_ntt , ntime_max ,
01441 ADN_ttdel , TS_dt ,
01442 ADN_ttorg , 0.0 ,
01443 ADN_ttdur , 0.0 ,
01444 ADN_tunits , UNITS_SEC_TYPE ,
01445 ADN_none ) ;
01446 }
01447
01448 if( ISFUNC(new_dset) && ! ISFUNCBUCKET(new_dset) && new_dset->taxis != NULL )
01449 EDIT_dset_items( new_dset , ADN_func_type , FUNC_FIM_TYPE , ADN_none ) ;
01450 else if( ISANATBUCKET(new_dset) )
01451 EDIT_dset_items( new_dset , ADN_func_type , ANAT_EPI_TYPE , ADN_none ) ;
01452
01453 if( THD_is_file(new_dset->dblk->diskptr->header_name) )
01454 ERROR_exit("Output file %s already exists -- cannot continue!\n",
01455 new_dset->dblk->diskptr->header_name ) ;
01456
01457 for (ids=0; ids<26; ids++)
01458 atoz[ids] = (double *) malloc(sizeof(double) * VSIZE ) ;
01459
01460 for( ids=0 ; ids < 26 ; ids++ )
01461 for (ii=0; ii<VSIZE; ii++)
01462 atoz[ids][ii] = 0.0 ;
01463
01464
01465
01466 nx = DSET_NX(new_dset) ;
01467 nxy = nx * DSET_NY(new_dset) ; daxes = new_dset->daxes ;
01468
01469 buf = (float **) malloc(sizeof(float *) * ntime_max);
01470
01471 for ( kt = 0 ; kt < ntime_max ; kt ++ ) {
01472
01473 if( CALC_verbose )
01474 INFO_message("Computing sub-brick %d\n",kt) ;
01475
01476
01477
01478 buf[kt] = (float *) malloc(sizeof(float) * CALC_nvox);
01479 if( buf[kt] == NULL )
01480 ERROR_exit("Can't malloc output dataset sub-brick %d!\n",kt) ;
01481
01482
01483
01484 for ( ii = 0 ; ii < CALC_nvox ; ii += VSIZE ) {
01485
01486 jbot = ii ;
01487 jtop = MIN( ii + VSIZE , CALC_nvox ) ;
01488
01489
01490
01491 if( CALC_has_xyz ){
01492 for( jj=jbot ; jj < jtop ; jj++ ){
01493 LOAD_IVEC3( iv , jj%nx , (jj%nxy)/nx , jj/nxy ) ;
01494 fv = THD_3dind_to_3dmm( new_dset , iv ) ;
01495 if( CALC_mangle_xyz )
01496 fv = THD_3dmm_to_dicomm(new_dset,fv) ;
01497 UNLOAD_FVEC3(fv,xxx[jj-jbot],yyy[jj-jbot],zzz[jj-jbot]) ;
01498 if( CALC_mangle_xyz == MANGLE_LPI ){
01499 xxx[jj-jbot] = -xxx[jj-jbot] ; yyy[jj-jbot] = -yyy[jj-jbot] ;
01500 }
01501 }
01502 }
01503
01504
01505
01506 for (ids = 0 ; ids < 26 ; ids ++ ) {
01507
01508
01509
01510
01511 if( TS_flim[ids] != NULL ){
01512 if( jbot == 0 ){
01513 double tval ;
01514 if( kt < TS_flim[ids]->nx ) tval = TS_flar[ids][kt] ;
01515 else tval = 0.0 ;
01516
01517 for (jj =jbot ; jj < jtop ; jj ++ )
01518 atoz[ids][jj-ii] = tval ;
01519 }
01520 }
01521
01522
01523
01524 else if( IJKAR_flim[ids] != NULL ){
01525 int ss , ix=IJKAR_flim[ids]->nx ;
01526
01527 switch( IJKAR_dcod[ids] ){
01528 case 8:
01529 for( jj=jbot ; jj < jtop ; jj++ ){
01530 ss = (jj%nx) ;
01531 atoz[ids][jj-jbot] = (ss < ix) ? IJKAR_flar[ids][ss] : 0.0 ;
01532 }
01533 break ;
01534 case 9:
01535 for( jj=jbot ; jj < jtop ; jj++ ){
01536 ss = ((jj%nxy)/nx) ;
01537 atoz[ids][jj-jbot] = (ss < ix) ? IJKAR_flar[ids][ss] : 0.0 ;
01538 }
01539 break ;
01540 case 10:
01541 for( jj=jbot ; jj < jtop ; jj++ ){
01542 ss = (jj/nxy) ;
01543 atoz[ids][jj-jbot] = (ss < ix) ? IJKAR_flar[ids][ss] : 0.0 ;
01544 }
01545 break ;
01546 }
01547 }
01548
01549
01550
01551 else if( CALC_dshift[ids] >= 0 ){
01552 int jds = CALC_dshift[ids] ;
01553 int kts , jjs , ix,jy,kz ;
01554 int id=CALC_dshift_i[ids] , jd=CALC_dshift_j[ids] ,
01555 kd=CALC_dshift_k[ids] , ld=CALC_dshift_l[ids] ;
01556 int ijkd = ((id!=0) || (jd!=0) || (kd!=0)) ;
01557 int dsx = DSET_NX(CALC_dset[jds]) - 1 ;
01558 int dsy = DSET_NY(CALC_dset[jds]) - 1 ;
01559 int dsz = DSET_NZ(CALC_dset[jds]) - 1 ;
01560 int dst = ntime[jds] - 1 ;
01561 int mode = CALC_dshift_mode[ids] , dun=0 ;
01562
01563 kts = kt + ld ;
01564 if( kts < 0 || kts > dst ){
01565 switch( mode ){
01566 case DSHIFT_MODE_ZERO:
01567 for( jj=jbot ; jj < jtop ; jj++ ) atoz[ids][jj-ii] = 0.0 ;
01568 dun = 1 ;
01569 break ;
01570 default:
01571 case DSHIFT_MODE_STOP:
01572 if( kts < 0 ) kts = 0 ;
01573 else if( kts > dst ) kts = dst ;
01574 break ;
01575 case DSHIFT_MODE_WRAP:
01576 while( kts < 0 ) kts += (dst+1) ;
01577 while( kts > dst ) kts -= (dst+1) ;
01578 break ;
01579 }
01580 }
01581
01582 if( !dun ){
01583 for( dun=0,jj=jbot ; jj < jtop ; jj++ ){
01584 jjs = jj ;
01585 if( ijkd ){
01586 ix = DSET_index_to_ix(CALC_dset[jds],jj) ;
01587 jy = DSET_index_to_jy(CALC_dset[jds],jj) ;
01588 kz = DSET_index_to_kz(CALC_dset[jds],jj) ;
01589
01590 ix += id ;
01591 if( ix < 0 || ix > dsx ){
01592 switch( mode ){
01593 case DSHIFT_MODE_ZERO:
01594 atoz[ids][jj-ii] = 0.0 ; dun = 1 ;
01595 break ;
01596 default:
01597 case DSHIFT_MODE_STOP:
01598 if( ix < 0 ) ix = 0 ;
01599 else if( ix > dsx ) ix = dsx ;
01600 break ;
01601 case DSHIFT_MODE_WRAP:
01602 while( ix < 0 ) ix += (dsx+1) ;
01603 while( ix > dsx ) ix -= (dsx+1) ;
01604 break ;
01605 }
01606 }
01607 if( dun ){ dun=0; continue; }
01608
01609 jy += jd ;
01610 if( jy < 0 || jy > dsy ){
01611 switch( mode ){
01612 case DSHIFT_MODE_ZERO:
01613 atoz[ids][jj-ii] = 0.0 ; dun = 1 ;
01614 break ;
01615 default:
01616 case DSHIFT_MODE_STOP:
01617 if( jy < 0 ) jy = 0 ;
01618 else if( jy > dsy ) jy = dsy ;
01619 break ;
01620 case DSHIFT_MODE_WRAP:
01621 while( jy < 0 ) jy += (dsy+1) ;
01622 while( jy > dsy ) jy -= (dsy+1) ;
01623 break ;
01624 }
01625 }
01626 if( dun ){ dun=0; continue; }
01627
01628 kz += kd ;
01629 if( kz < 0 || kz > dsz ){
01630 switch( mode ){
01631 case DSHIFT_MODE_ZERO:
01632 atoz[ids][jj-ii] = 0.0 ; dun = 1 ;
01633 break ;
01634 default:
01635 case DSHIFT_MODE_STOP:
01636 if( kz < 0 ) kz = 0 ;
01637 else if( kz > dsz ) kz = dsz ;
01638 break ;
01639 case DSHIFT_MODE_WRAP:
01640 while( kz < 0 ) kz += (dsz+1) ;
01641 while( kz > dsz ) kz -= (dsz+1) ;
01642 break ;
01643 }
01644 }
01645 if( dun ){ dun=0; continue; }
01646
01647 jjs = DSET_ixyz_to_index(CALC_dset[jds],ix,jy,kz) ;
01648 }
01649 switch( CALC_type[jds] ) {
01650 case MRI_short:
01651 atoz[ids][jj-ii] = CALC_short[jds][kts][jjs]
01652 * CALC_ffac[jds][kts];
01653 break ;
01654 case MRI_float:
01655 atoz[ids][jj-ii] = CALC_float[jds][kts][jjs]
01656 * CALC_ffac[jds][kts];
01657 break ;
01658 case MRI_byte:
01659 atoz[ids][jj-ii] = CALC_byte[jds][kts][jjs]
01660 * CALC_ffac[jds][kts];
01661 break ;
01662 case MRI_rgb:
01663 atoz[ids][jj-ii] = Rfac*CALC_byte[jds][kts][3*jjs ]
01664 +Gfac*CALC_byte[jds][kts][3*jjs+1]
01665 +Bfac*CALC_byte[jds][kts][3*jjs+2] ;
01666 break ;
01667 }
01668 }
01669 }
01670 }
01671
01672
01673
01674 else if ( ntime[ids] == 1 && CALC_type[ids] >= 0 ) {
01675 switch( CALC_type[ids] ) {
01676 case MRI_short:
01677 if( CALC_noffac[ids] )
01678 for (jj =jbot ; jj < jtop ; jj ++ )
01679 atoz[ids][jj-ii] = CALC_short[ids][0][jj] ;
01680 else
01681 for (jj =jbot ; jj < jtop ; jj ++ )
01682 atoz[ids][jj-ii] = CALC_short[ids][0][jj] * CALC_ffac[ids][0] ;
01683 break;
01684
01685 case MRI_float:
01686 if( CALC_noffac[ids] )
01687 for (jj =jbot ; jj < jtop ; jj ++ )
01688 atoz[ids][jj-ii] = CALC_float[ids][0][jj] ;
01689 else
01690 for (jj =jbot ; jj < jtop ; jj ++ )
01691 atoz[ids][jj-ii] = CALC_float[ids][0][jj] * CALC_ffac[ids][0] ;
01692 break;
01693
01694 case MRI_byte:
01695 if( CALC_noffac[ids] )
01696 for (jj =jbot ; jj < jtop ; jj ++ )
01697 atoz[ids][jj-ii] = CALC_byte[ids][0][jj] ;
01698 else
01699 for (jj =jbot ; jj < jtop ; jj ++ )
01700 atoz[ids][jj-ii] = CALC_byte[ids][0][jj] * CALC_ffac[ids][0] ;
01701 break;
01702
01703 case MRI_rgb:
01704 for (jj =jbot ; jj < jtop ; jj ++ )
01705 atoz[ids][jj-ii] = Rfac*CALC_byte[ids][0][3*jj ]
01706 +Gfac*CALC_byte[ids][0][3*jj+1]
01707 +Bfac*CALC_byte[ids][0][3*jj+2] ;
01708 break;
01709 }
01710 }
01711
01712
01713
01714 else if( ntime[ids] > 1 && CALC_type[ids] >= 0 ) {
01715 switch ( CALC_type[ids] ) {
01716 case MRI_short:
01717 if( CALC_noffac[ids] )
01718 for (jj = jbot ; jj < jtop ; jj ++ )
01719 atoz[ids][jj-ii] = CALC_short[ids][kt][jj] ;
01720 else
01721 for (jj = jbot ; jj < jtop ; jj ++ )
01722 atoz[ids][jj-ii] = CALC_short[ids][kt][jj] * CALC_ffac[ids][kt];
01723 break;
01724
01725 case MRI_float:
01726 if( CALC_noffac[ids] )
01727 for (jj = jbot ; jj < jtop ; jj ++ )
01728 atoz[ids][jj-ii] = CALC_float[ids][kt][jj] ;
01729 else
01730 for (jj = jbot ; jj < jtop ; jj ++ )
01731 atoz[ids][jj-ii] = CALC_float[ids][kt][jj] * CALC_ffac[ids][kt];
01732 break;
01733
01734 case MRI_byte:
01735 if( CALC_noffac[ids] )
01736 for (jj = jbot ; jj < jtop ; jj ++ )
01737 atoz[ids][jj-ii] = CALC_byte[ids][kt][jj] ;
01738 else
01739 for (jj = jbot ; jj < jtop ; jj ++ )
01740 atoz[ids][jj-ii] = CALC_byte[ids][kt][jj] * CALC_ffac[ids][kt];
01741 break;
01742
01743 case MRI_rgb:
01744 for (jj =jbot ; jj < jtop ; jj ++ )
01745 atoz[ids][jj-ii] = Rfac*CALC_byte[ids][kt][3*jj ]
01746 +Gfac*CALC_byte[ids][kt][3*jj+1]
01747 +Bfac*CALC_byte[ids][kt][3*jj+2] ;
01748 break;
01749 }
01750 }
01751
01752
01753
01754 else if( CALC_has_predefined ) {
01755
01756 switch( ids ){
01757 case 23:
01758 if( HAS_X )
01759 for( jj=jbot ; jj < jtop ; jj++ )
01760 atoz[ids][jj-ii] = xxx[jj-ii] ;
01761 break ;
01762
01763 case 24:
01764 if( HAS_Y )
01765 for( jj=jbot ; jj < jtop ; jj++ )
01766 atoz[ids][jj-ii] = yyy[jj-ii] ;
01767 break ;
01768
01769 case 25:
01770 if( HAS_Z )
01771 for( jj=jbot ; jj < jtop ; jj++ )
01772 atoz[ids][jj-ii] = zzz[jj-ii] ;
01773 break ;
01774
01775 case 8:
01776 if( HAS_I )
01777 for( jj=jbot ; jj < jtop ; jj++ )
01778 atoz[ids][jj-ii] = (jj%nx) ;
01779 break ;
01780
01781 case 9:
01782 if( HAS_J )
01783 for( jj=jbot ; jj < jtop ; jj++ )
01784 atoz[ids][jj-ii] = ((jj%nxy)/nx) ;
01785 break ;
01786
01787 case 10:
01788 if( HAS_K )
01789 for( jj=jbot ; jj < jtop ; jj++ )
01790 atoz[ids][jj-ii] = (jj/nxy) ;
01791 break ;
01792
01793 case 19:
01794 if( HAS_T )
01795 for( jj=jbot ; jj < jtop ; jj++ )
01796 atoz[ids][jj-ii] = THD_timeof_vox(kt,jj,new_dset) ;
01797 break ;
01798
01799 case 11:
01800 if( HAS_L )
01801 for( jj=jbot ; jj < jtop ; jj++ )
01802 atoz[ids][jj-ii] = kt ;
01803 break ;
01804 }
01805
01806 }
01807 }
01808
01809
01810
01811 PARSER_evaluate_vector(CALC_code, atoz, jtop-jbot, temp);
01812 for ( jj = jbot ; jj < jtop ; jj ++ )
01813 buf[kt][jj] = temp[jj-ii];
01814
01815 }
01816
01817
01818
01819 nbad = thd_floatscan( CALC_nvox , buf[kt] ) ;
01820 if( nbad > 0 )
01821 WARNING_message("%d bad floats replaced by 0 in sub-brick %d\n\a",
01822 nbad , kt ) ;
01823
01824
01825
01826 if( ! CALC_has_timeshift ){
01827 for( ids=0 ; ids < 26 ; ids ++ ){
01828 if( CALC_dset[ids] != NULL && ntime[ids] > 1 &&
01829 CALC_dset[ids]->dblk->malloc_type == DATABLOCK_MEM_MALLOC ){
01830
01831 void * ptr = DSET_ARRAY(CALC_dset[ids],kt) ;
01832 if( ptr != NULL ) free(ptr) ;
01833 mri_clear_data_pointer( DSET_BRICK(CALC_dset[ids],kt) ) ;
01834 }
01835 }
01836 }
01837
01838 }
01839
01840 for( ids=0 ; ids < 26 ; ids++ ){
01841 if( CALC_dset[ids] != NULL ) PURGE_DSET( CALC_dset[ids] ) ;
01842 if( TS_flim[ids] != NULL ) mri_free( TS_flim[ids] ) ;
01843 if( IJKAR_flim[ids]!= NULL ) mri_free( IJKAR_flim[ids] ) ;
01844 }
01845
01846
01847
01848 switch( CALC_datum ){
01849
01850 default:
01851 ERROR_exit("Somehow ended up with CALC_datum = %d\n",CALC_datum) ;
01852 exit(1) ;
01853
01854
01855
01856 case MRI_float:{
01857 for( ii=0 ; ii < ntime_max ; ii++ ){
01858 EDIT_substitute_brick(new_dset, ii, MRI_float, buf[ii]);
01859 DSET_BRICK_FACTOR(new_dset, ii) = 0.0;
01860 }
01861 }
01862 break ;
01863
01864
01865
01866 case MRI_byte:
01867 case MRI_short:{
01868 void ** dfim ;
01869 float gtop , fimfac , gtemp ;
01870
01871 if( CALC_verbose )
01872 INFO_message("Scaling output to type %s brick(s)\n",
01873 MRI_TYPE_name[CALC_datum] ) ;
01874
01875 dfim = (void ** ) malloc( sizeof( void * ) * ntime_max ) ;
01876
01877 if( CALC_gscale ){
01878 gtop = 0.0 ;
01879 for( ii=0 ; ii < ntime_max ; ii++ ){
01880 gtemp = MCW_vol_amax( CALC_nvox , 1 , 1 , MRI_float, buf[ii] ) ;
01881 gtop = MAX( gtop , gtemp ) ;
01882 if( gtemp == 0.0 )
01883 WARNING_message("output sub-brick %d is all zeros!\n",ii) ;
01884 }
01885 }
01886
01887 for (ii = 0 ; ii < ntime_max ; ii ++ ) {
01888
01889
01890
01891 if( ! CALC_gscale ){
01892 gtop = MCW_vol_amax( CALC_nvox , 1 , 1 , MRI_float, buf[ii] ) ;
01893 if( gtop == 0.0 )
01894 WARNING_message("output sub-brick %d is all zeros!\n",ii) ;
01895 }
01896
01897
01898
01899 if( CALC_fscale ){
01900 fimfac = (gtop > 0.0) ? MRI_TYPE_maxval[CALC_datum] / gtop : 0.0 ;
01901
01902 } else if( !CALC_nscale ){
01903
01904 fimfac = (gtop > MRI_TYPE_maxval[CALC_datum] || (gtop > 0.0 && gtop <= 1.0) )
01905 ? MRI_TYPE_maxval[CALC_datum]/ gtop : 0.0 ;
01906
01907 if( fimfac == 0.0 && gtop > 0.0 ){
01908 float fv,iv ; int kk ;
01909 for( kk=0 ; kk < CALC_nvox ; kk++ ){
01910 fv = buf[ii][kk] ; iv = rint(fv) ;
01911 if( fabs(fv-iv) >= 0.01 ){
01912 fimfac = MRI_TYPE_maxval[CALC_datum]/ gtop ; break ;
01913 }
01914 }
01915 }
01916
01917 } else {
01918 fimfac = 0.0 ;
01919 }
01920
01921 if( CALC_verbose ){
01922 if( fimfac != 0.0 )
01923 INFO_message("Sub-brick %d scale factor = %f\n",ii,fimfac) ;
01924 else
01925 INFO_message("Sub-brick %d: no scale factor\n" ,ii) ;
01926 }
01927
01928
01929
01930 dfim[ii] = (void *) malloc( mri_datum_size(CALC_datum) * CALC_nvox ) ;
01931 if( dfim[ii] == NULL ) ERROR_exit("malloc fails at output[%d]\n",ii);
01932
01933 if( CALC_datum == MRI_byte ){
01934 int nneg ;
01935 for( nneg=jj=0 ; jj < CALC_nvox ; jj++ ) nneg += (buf[ii][jj] < 0.0f) ;
01936 if( nneg > 0 )
01937 WARNING_message(
01938 "sub-brick #%d has %d negative values set=0 in conversion to bytes\n",
01939 ii , nneg ) ;
01940 }
01941
01942 EDIT_coerce_scale_type( CALC_nvox , fimfac ,
01943 MRI_float, buf[ii] , CALC_datum,dfim[ii] ) ;
01944 free( buf[ii] ) ;
01945
01946
01947
01948 EDIT_substitute_brick(new_dset, ii, CALC_datum, dfim[ii] );
01949
01950 DSET_BRICK_FACTOR(new_dset,ii) = (fimfac != 0.0) ? 1.0/fimfac : 0.0 ;
01951 }
01952 }
01953 break ;
01954 }
01955
01956 if( CALC_verbose ) INFO_message("Computing output statistics\n") ;
01957 THD_load_statistics( new_dset ) ;
01958
01959 THD_write_3dim_dataset( NULL,NULL , new_dset , True ) ;
01960 if( CALC_verbose ) WROTE_DSET(new_dset) ;
01961
01962 exit(0) ;
01963 }