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 #define PROGRAM_NAME "3dmerge"              
00032 #define LAST_MOD_DATE "02 Nov 2001"         
00033 
00034 #include "mrilib.h"
00035 #include "parser.h"    
00036 
00037 #define MAIN
00038 #define MEGA  1048576  
00039 
00040 #ifndef myXtFree
00041 #define myXtFree(xp) (XtFree((char *)(xp)) , (xp)=NULL)
00042 #endif
00043 
00044 #define ALLOW_SUBV  
00045 
00046 #ifdef ALLOW_SUBV
00047 # define DSET_OPEN THD_open_dataset
00048 #else
00049 # define DSET_OPEN THD_open_one_dataset
00050 #endif
00051 
00052 
00053 
00054 
00055 
00056 #define CFLAG_MEAN   1  
00057 #define CFLAG_NZMEAN 2
00058 #define CFLAG_MMAX   3
00059 #define CFLAG_COUNT  4
00060 #define CFLAG_AMAX   5
00061 #define CFLAG_SMAX   6
00062 #define CFLAG_ORDER  7
00063 #define CFLAG_FISHER 8  
00064 
00065 #define THFLAG_NONE  0    
00066 #define THFLAG_FICO  71   
00067 
00068 #define TANH(z)   tanh(z)  
00069 #define ATANH(z) atanh(z)
00070 
00071 
00072 
00073 static EDIT_options MRG_edopt ;
00074 static int MRG_have_edopt = 0 ;
00075 
00076 static int   MRG_hits_g       = 0 ;
00077 static int   MRG_cflag_g      = CFLAG_MEAN ;
00078 static int   MRG_keepthr      = 0 ;
00079 static float MRG_clust_rmm_g  = 0.0 ;
00080 static float MRG_clust_vmul_g = 0.0 ;
00081 static int   MRG_datum        = ILLEGAL_TYPE ;
00082 static int   MRG_thdatum      = ILLEGAL_TYPE ;
00083 static int   MRG_be_quiet     = 0 ;
00084 static int   MRG_cflag_gthr   = THFLAG_NONE ;  
00085 static int   MRG_doall        = 0;             
00086 static int   MRG_verbose      = 0;             
00087 
00088 static char  MRG_output_session[THD_MAX_NAME]   = "./" ;
00089 static char  MRG_output_prefix [THD_MAX_PREFIX] = "mrg" ;
00090 #if 0
00091 static char  MRG_output_label  [THD_MAX_LABEL]  = "\0" ;
00092 #endif
00093 
00094 static int   MRG_ivfim = -1 ;
00095 static int   MRG_ivthr = -1 ;
00096 
00097 static int   MRG_nscale = 0 ; 
00098 
00099 
00100 int MRG_read_opts( int , char ** ) ;
00101 void MRG_Syntax(void) ;
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 #ifdef MERGE_DEBUG
00110 #  define DUMP1 fprintf(stderr,"ARG: %s\n",argv[nopt])
00111 #  define DUMP2 fprintf(stderr,"ARG: %s %s\n",argv[nopt],argv[nopt+1])
00112 #  define DUMP3 fprintf(stderr,"ARG: %s %s %s\n",argv[nopt],argv[nopt+1],argv[nopt+2])
00113 #else
00114 #  define DUMP1
00115 #  define DUMP2
00116 #  define DUMP3
00117 #endif
00118 
00119 int MRG_read_opts( int argc , char * argv[] )
00120 {
00121    int nopt = 1 ;
00122    float val ;
00123    int  ival ;
00124 
00125    INIT_EDOPT( &MRG_edopt ) ;
00126 
00127    while( nopt < argc && argv[nopt][0] == '-' ){
00128 
00129       
00130 
00131       ival = EDIT_check_argv( argc , argv , nopt , &MRG_edopt ) ;
00132       if( ival > 0 ){
00133          nopt += ival ; MRG_have_edopt = 1 ;
00134          continue ;
00135       }
00136 
00137       
00138 
00139       if( strncmp(argv[nopt],"-verb",5) == 0 ){
00140         MRG_verbose = MRG_edopt.verbose = 1 ;
00141         nopt++ ; continue ;
00142       }
00143 
00144       
00145 
00146       if( strncmp(argv[nopt],"-1dindex",5) == 0 ){
00147          if( ++nopt >= argc ){
00148             fprintf(stderr,"need an argument after -1dindex!\n") ; exit(1) ;
00149          }
00150          MRG_ivfim = MRG_edopt.iv_fim = (int) strtod( argv[nopt++] , NULL ) ;
00151          continue ;
00152       }
00153 
00154       if( strncmp(argv[nopt],"-1tindex",5) == 0 ){
00155          if( ++nopt >= argc ){
00156             fprintf(stderr,"need an argument after -1tindex!\n") ; exit(1) ;
00157          }
00158          MRG_ivthr = MRG_edopt.iv_thr = (int) strtod( argv[nopt++] , NULL ) ;
00159          continue ;
00160       }
00161 
00162       
00163 
00164       if( strncmp(argv[nopt],"-1fmask",6) == 0 ){
00165          THD_3dim_dataset * mset ; int nn ;
00166 
00167          if( MRG_edopt.nfmask > 0 ){
00168             fprintf(stderr,"Can't have 2 -fmask options!\n") ;
00169             exit(1) ;
00170          }
00171          if( ++nopt >= argc ){
00172             fprintf(stderr,"No argument after %s?\n",argv[nopt-1]) ;
00173             exit(1);
00174          }
00175 
00176          mset = THD_open_dataset( argv[nopt++] ) ;
00177          if( mset == NULL ){
00178             fprintf(stderr,"*** Can't open -fmask dataset\n") ;
00179             exit(1) ;
00180          }
00181          if( DSET_BRICK_TYPE(mset,0) == MRI_complex ){
00182             fprintf(stderr,"*** Can't deal with complex-valued -fmask dataset\n");
00183             exit(1) ;
00184          }
00185 
00186          MRG_edopt.fmask  = THD_makemask( mset , 0 , 666.0,-666.0 ) ;
00187          MRG_edopt.nfmask = DSET_NVOX(mset) ;
00188 
00189          nn = THD_countmask(MRG_edopt.nfmask,MRG_edopt.fmask) ;
00190          if( nn < 2 ){
00191             fprintf(stderr,"*** Too few (%d) nonzero voxels in -fmask!\n",nn) ;
00192             exit(1) ;
00193          }
00194 
00195          DSET_delete(mset) ;
00196 
00197          if( MRG_edopt.filter_opt == FCFLAG_AVER )
00198             MRG_edopt.filter_opt = FCFLAG_MEAN ;
00199 
00200          if( MRG_edopt.thrfilter_opt == FCFLAG_AVER )
00201             MRG_edopt.thrfilter_opt = FCFLAG_MEAN ;
00202 
00203          continue ;
00204       }
00205 
00206       
00207 
00208       if( strcmp(argv[nopt],"-1filter_winsor") == 0 ){
00209          int nwin ;
00210 
00211          nopt++ ;
00212          if( nopt+1 >= argc ){
00213             fprintf(stderr,"*** Need 2 arguments after -1filter_winsor\n") ;
00214             exit(1) ;
00215          }
00216          MRG_edopt.filter_rmm  = strtod( argv[nopt++] , NULL ) ;
00217          if( MRG_edopt.filter_rmm <= 0.0 ){
00218             fprintf(stderr,"*** Illegal rmm value after -1filter_winsor\n");
00219             exit(1) ;
00220          }
00221          nwin = (int) strtod( argv[nopt++] , NULL ) ;
00222          if( nwin <= 0 || nwin >= FCFLAG_ONE_STEP ){
00223             fprintf(stderr,"*** Illegal nw value after -1filter_winsor\n");
00224             exit(1) ;
00225          }
00226          MRG_edopt.filter_opt = FCFLAG_WINSOR + nwin ;
00227          MRG_have_edopt = 1 ; continue ;
00228       }
00229 
00230       
00231 
00232       if( strncmp(argv[nopt],"-1filter_expr",13) == 0 ){
00233          PARSER_code * pcode ; int hsym[26] , aa , naa , nee ;
00234          double atoz[26] , val ;
00235 
00236          nopt++ ;
00237          if( nopt+1 >= argc ){
00238             fprintf(stderr,"*** Need 2 arguments after -1filter_expr\n") ;
00239             exit(1) ;
00240          }
00241          MRG_edopt.filter_opt = FCFLAG_EXPR;
00242          MRG_edopt.filter_rmm  = strtod( argv[nopt++] , NULL ) ;
00243          if( MRG_edopt.filter_rmm <= 0.0 ){
00244             fprintf(stderr,"*** Illegal rmm value after -1filter_expr\n");
00245             exit(1) ;
00246          }
00247 
00248          MRG_edopt.fexpr = argv[nopt++] ;
00249          pcode = PARSER_generate_code( MRG_edopt.fexpr ) ;  
00250 
00251          if( pcode == NULL ){
00252             fprintf(stderr,"*** Illegal expr after -1filter_expr\n");
00253             exit(1);
00254          }
00255 
00256 #undef   MASK
00257 #undef   PREDEFINED_MASK
00258 #define  MASK(x)          (1 << (x-'a'))
00259 #define  PREDEFINED_MASK  ( MASK('r') | MASK('x') | MASK('y') | MASK('z')   \
00260                                       | MASK('i') | MASK('j') | MASK('k') )
00261 
00262          
00263 
00264          PARSER_mark_symbols( pcode , hsym ) ;  
00265 
00266          for( nee=naa=aa=0 ; aa < 26 ; aa++ ){
00267             if( hsym[aa] ){
00268                if( ((1<<aa) & PREDEFINED_MASK) == 0 ){
00269                   nee++ ;  
00270                   fprintf(stderr,"*** Symbol %c in -1filter_expr is illegal\n",'a'+aa) ;
00271                } else {
00272                   naa++ ;  
00273                }
00274             }
00275          }
00276          if( nee > 0 ) exit(1) ;  
00277          if( naa == 0 ){          
00278             double atoz[26] , val ;
00279             val = PARSER_evaluate_one( pcode , atoz ) ;
00280             if( val != 0.0 ){
00281                fprintf(stderr,"+++ Warning: -1filter_expr is constant = %g\n",val) ;
00282             } else {
00283                fprintf(stderr,"*** -1filter_expr is identically zero\n") ;
00284                exit(1) ;
00285             }
00286          }
00287 
00288          free(pcode) ;  
00289 
00290          MRG_have_edopt = 1 ; continue ;
00291       }
00292 
00293       
00294 
00295       if( strncmp(argv[nopt],"-quiet",6) == 0 ){
00296          MRG_be_quiet = 1 ;
00297          nopt++ ; continue ;
00298       }
00299 
00300 
00301       
00302 
00303       if( strncmp(argv[nopt],"-keepthr",6) == 0 ){
00304          MRG_keepthr = 1 ;
00305          nopt++ ; continue ;
00306       }
00307 
00308          
00309 
00310       if( strncmp(argv[nopt],"-doall",6) == 0 ){
00311          MRG_doall = 1 ;
00312          nopt++ ; continue ;
00313       }
00314 
00315       
00316 
00317       if( strncmp(argv[nopt],"-datum",6) == 0 ){
00318 DUMP2 ;
00319          if( ++nopt >= argc ){
00320             fprintf(stderr,"need an argument after -datum!\n") ; exit(1) ;
00321          }
00322 
00323          if( strcmp(argv[nopt],"short") == 0 ){
00324             MRG_datum = MRI_short ;
00325          } else if( strcmp(argv[nopt],"float") == 0 ){
00326             MRG_datum = MRI_float ;
00327          } else if( strcmp(argv[nopt],"byte") == 0 ){
00328             MRG_datum = MRI_byte ;
00329          } else if( strcmp(argv[nopt],"complex") == 0 ){  
00330             MRG_datum = MRI_complex ;
00331          } else {
00332             fprintf(stderr,"-datum of type '%s' is not supported in 3dmerge!\n",
00333                     argv[nopt] ) ;
00334             exit(1) ;
00335          }
00336          nopt++ ; continue ;  
00337       }
00338 
00339       
00340 
00341       if( strncmp(argv[nopt],"-thdatum",6) == 0 ){
00342 DUMP2 ;
00343          if( ++nopt >= argc ){
00344             fprintf(stderr,"need an argument after -thdatum!\n") ; exit(1) ;
00345          }
00346 
00347          if( strcmp(argv[nopt],"short") == 0 ){
00348             MRG_thdatum = MRI_short ;
00349          } else if( strcmp(argv[nopt],"float") == 0 ){
00350             MRG_thdatum = MRI_float ;
00351          } else if( strcmp(argv[nopt],"byte") == 0 ){
00352             MRG_thdatum = MRI_byte ;
00353          } else {
00354             fprintf(stderr,"-thdatum of type '%s' is not supported in 3dmerge!\n",
00355                     argv[nopt] ) ;
00356             exit(1) ;
00357          }
00358          MRG_keepthr = 1 ;    
00359          nopt++ ; continue ;  
00360       }
00361 
00362       
00363 
00364       if( strncmp(argv[nopt],"-ghits",6) == 0 ){
00365 DUMP2 ;
00366          nopt++ ;
00367          if( nopt >= argc ){
00368             fprintf(stderr,"need argument after -ghits!\n") ; exit(1) ;
00369          }
00370          MRG_hits_g = strtod( argv[nopt++] , NULL ) ;
00371          if( MRG_hits_g <= 0 ){
00372             fprintf(stderr,"illegal value after -ghits\n") ;
00373             exit(1) ;
00374          }
00375          continue ;
00376       }
00377 
00378       
00379 
00380       if( strncmp(argv[nopt],"-gclust",6) == 0 ){
00381 DUMP3 ;
00382          nopt++ ;
00383          if( nopt+1 >= argc ){
00384             fprintf(stderr,"need 2 arguments after -gclust!\n") ;
00385             exit(1) ;
00386          }
00387          MRG_clust_rmm_g  = strtod( argv[nopt++] , NULL ) ;
00388          MRG_clust_vmul_g = strtod( argv[nopt++] , NULL ) ;
00389          if( MRG_clust_rmm_g <= 0 || MRG_clust_vmul_g <= 0 ){
00390             fprintf(stderr,"illegal value after -gclust\n") ;
00391             exit(1) ;
00392          }
00393          continue ;
00394       }
00395 
00396       
00397 
00398       if( strncmp(argv[nopt],"-session",6) == 0 ){
00399 DUMP2 ;
00400          nopt++ ;
00401          if( nopt >= argc ){
00402             fprintf(stderr,"need argument after -session!\n") ;
00403             exit(1) ;
00404          }
00405          MCW_strncpy( MRG_output_session , argv[nopt++] , THD_MAX_NAME ) ;
00406          continue ;
00407       }
00408 
00409       
00410 
00411       if( strncmp(argv[nopt],"-prefix",6) == 0 ){
00412 DUMP2 ;
00413          nopt++ ;
00414          if( nopt >= argc ){
00415             fprintf(stderr,"need argument after -prefix!\n") ;
00416             exit(1) ;
00417          }
00418          MCW_strncpy( MRG_output_prefix , argv[nopt++] , THD_MAX_PREFIX ) ;
00419          continue ;
00420       }
00421 
00422 #if 0
00423       
00424 
00425       if( strncmp(argv[nopt],"-label",6) == 0 ){
00426 DUMP2 ;
00427          nopt++ ;
00428          if( nopt >= argc ){
00429             fprintf(stderr,"need argument after -label!\n") ;
00430             exit(1) ;
00431          }
00432          MCW_strncpy( MRG_output_label , argv[nopt++] , THD_MAX_LABEL ) ;
00433          continue ;
00434       }
00435 #endif
00436 
00437       
00438 
00439       if( strcmp(argv[nopt],"-nscale") == 0 ){
00440 DUMP1 ;
00441          MRG_nscale = 1 ;
00442          nopt++ ; continue ;
00443       }
00444 
00445 
00446       
00447 
00448       if( strncmp(argv[nopt],"-gmean",6) == 0 ){
00449 DUMP1 ;
00450          MRG_cflag_g = CFLAG_MEAN ;
00451          nopt++ ; continue ;
00452       }
00453 
00454       
00455 
00456       if( strncmp(argv[nopt],"-gfisher",6) == 0 ){
00457 DUMP1 ;
00458          MRG_cflag_g = CFLAG_FISHER ;
00459          nopt++ ; continue ;
00460       }
00461 
00462       
00463 
00464       if( strncmp(argv[nopt],"-tgfisher",6) == 0 ){
00465 DUMP1 ;
00466          MRG_cflag_gthr = THFLAG_FICO ;
00467          nopt++ ; continue ;
00468       }
00469 
00470       
00471 
00472       if( strncmp(argv[nopt],"-gnzmean",6) == 0 ){
00473 DUMP1 ;
00474          MRG_cflag_g = CFLAG_NZMEAN ;
00475          nopt++ ; continue ;
00476       }
00477 
00478       
00479 
00480       if( strncmp(argv[nopt],"-gmax",6) == 0 ){
00481 DUMP1 ;
00482          MRG_cflag_g = CFLAG_MMAX ;
00483          nopt++ ; continue ;
00484       }
00485 
00486       
00487 
00488       if( strncmp(argv[nopt],"-gamax",6) == 0 ){
00489 DUMP1 ;
00490          MRG_cflag_g = CFLAG_AMAX ;
00491          nopt++ ; continue ;
00492       }
00493 
00494       
00495 
00496       if( strncmp(argv[nopt],"-gsmax",6) == 0 ){
00497 DUMP1 ;
00498          MRG_cflag_g = CFLAG_SMAX ;
00499          nopt++ ; continue ;
00500       }
00501 
00502       
00503 
00504       if( strncmp(argv[nopt],"-gcount",6) == 0 ){
00505 DUMP1 ;
00506          MRG_cflag_g = CFLAG_COUNT ;
00507          nopt++ ; continue ;
00508       }
00509 
00510       
00511 
00512       if( strncmp(argv[nopt],"-gorder",6) == 0 ){
00513 DUMP1 ;
00514          MRG_cflag_g = CFLAG_ORDER ;
00515          nopt++ ; continue ;
00516       }
00517 
00518       
00519 
00520       fprintf(stderr,"unrecognized option %s\n",argv[nopt]) ;
00521       exit(1) ;
00522 
00523    }  
00524 
00525    
00526 
00527 #if 0
00528    if( strlen(MRG_output_label) == 0 ){
00529       MCW_strncpy( MRG_output_label , MRG_output_prefix , THD_MAX_LABEL ) ;
00530    }
00531 #endif
00532 
00533    return( nopt );
00534 }
00535 
00536 
00537 
00538 void MRG_Syntax(void)
00539 {
00540    printf(
00541     "Edit and/or merge 3D datasets\n"
00542     "Usage: 3dmerge [options] datasets ...\n"
00543     "where the options are:\n"
00544    ) ;
00545 
00546    printf( "%s\n" , EDIT_options_help() ) ;
00547 
00548    printf(
00549     "OTHER OPTIONS:\n"
00550     "  -datum type = Coerce the output data to be stored as the given type,\n"
00551     "                  which may be byte, short, or float.\n"
00552     "          N.B.: Byte data cannot be negative.  If this datum type is chosen,\n"
00553     "                  any negative values in the edited and/or merged dataset\n"
00554     "                  will be set to zero.\n"
00555     "  -keepthr    = When using 3dmerge to edit exactly one dataset of a\n"
00556     "                  functional type with a threshold statistic attached,\n"
00557     "                  normally the resulting dataset is of the 'fim'\n"
00558     "                  (intensity only) type.  This option tells 3dmerge to\n"
00559     "                  copy the threshold data (unedited in any way) into\n"
00560     "                  the output dataset.\n"
00561     "          N.B.: This option is ignored if 3dmerge is being used to\n"
00562     "                  combine 2 or more datasets.\n"
00563     "          N.B.: The -datum option has no effect on the storage of the\n"
00564     "                  threshold data.  Instead use '-thdatum type'.\n"
00565     "\n"
00566     "  -doall      = Apply editing and merging options to ALL sub-bricks \n"
00567     "                  uniformly in a dataset.\n"
00568     "          N.B.: All input datasets must have the same number of sub-bricks\n"
00569     "                  when using the -doall option. \n"
00570     "          N.B.: The threshold specific options (such as -1thresh, \n"
00571     "                  -keepthr, -tgfisher, etc.) are not compatible with \n"
00572     "                  the -doall command.  Neither are the -1dindex or\n"
00573     "                  the -1tindex options.\n"
00574     "          N.B.: All labels and statistical parameters for individual \n"
00575     "                  sub-bricks are copied from the first dataset.  It is \n"
00576     "                  the responsibility of the user to verify that these \n"
00577     "                  are appropriate.  Note that sub-brick auxiliary data \n"
00578     "                  can be modified using program 3drefit. \n"
00579     "\n"
00580     "  -1dindex j  = Uses sub-brick #j as the data source , and uses sub-brick\n"
00581     "  -1tindex k  = #k as the threshold source.  With these, you can operate\n"
00582     "                  on any given sub-brick of the inputs dataset(s) to produce\n"
00583     "                  as output a 1 brick dataset.  If desired, a collection\n"
00584     "                  of 1 brick datasets can later be assembled into a\n"
00585     "                  multi-brick bucket dataset using program '3dbucket'\n"
00586     "                  or into a 3D+time dataset using program '3dTcat'.\n"
00587     "          N.B.: If these options aren't used, j=0 and k=1 are the defaults\n"
00588     "\n"
00589     "  The following option allows you to specify a mask dataset that\n"
00590     "  limits the action of the 'filter' options to voxels that are\n"
00591     "  nonzero in the mask:\n"
00592     "\n"
00593     "  -1fmask mset = Read dataset 'mset' (which can include a\n"
00594     "                  sub-brick specifier) and use the nonzero\n"
00595     "                  voxels as a mask for the filter options.\n"
00596     "                  Filtering calculations will not use voxels\n"
00597     "                  that are outside the mask.  If an output\n"
00598     "                  voxel does not have ANY masked voxels inside\n"
00599     "                  the rmm radius, then that output voxel will\n"
00600     "                  be set to 0.\n"
00601     "         N.B.: * Only the -1filter_* and -t1filter_* options are\n"
00602     "                 affected by -1fmask.\n"
00603     "               * In the linear averaging filters (_mean, _nzmean,\n"
00604     "                 and _expr), voxels not in the mask will not be used\n"
00605     "                 or counted in either the numerator or denominator.\n"
00606     "                 This can give unexpected results.  If the mask is\n"
00607     "                 designed to exclude the volume outside the brain,\n"
00608     "                 then voxels exterior to the brain, but within 'rmm',\n"
00609     "                 will have a few voxels inside the brain included\n"
00610     "                 in the filtering.  Since the sum of weights (the\n"
00611     "                 denominator) is only over those few intra-brain\n"
00612     "                 voxels, the effect will be to extend the significant\n"
00613     "                 part of the result outward by rmm from the surface\n"
00614     "                 of the brain.  In contrast, without the mask, the\n"
00615     "                 many small-valued voxels outside the brain would\n"
00616     "                 be included in the numerator and denominator sums,\n"
00617     "                 which would barely change the numerator (since the\n"
00618     "                 voxel values are small outside the brain), but would\n"
00619     "                 increase the denominator greatly (by including many\n"
00620     "                 more weights).  The effect in this case (no -1fmask)\n"
00621     "                 is to make the filtering taper off gradually in the\n"
00622     "                 rmm-thickness shell around the brain.\n"
00623     "               * Thus, if the -1fmask is intended to clip off non-brain\n"
00624     "                 data from the filtering, its use should be followed by\n"
00625     "                 masking operation using 3dcalc:\n"
00626     "      3dmerge -1filter_aver 12 -1fmask mask+orig -prefix x input+orig\n"
00627     "      3dcalc  -a x -b mask+orig -prefix y -expr 'a*step(b)'\n"
00628     "      rm -f x+orig.*\n"
00629     "                 The desired result is y+orig - filtered using only\n"
00630     "                 brain voxels (as defined by mask+orig), and with\n"
00631     "                 the output confined to the brain voxels as well.\n"
00632     "\n"
00633     "  The following option allows you to specify an almost arbitrary\n"
00634     "  weighting function for 3D linear filtering:\n"
00635     "\n"
00636     "  -1filter_expr rmm expr\n"
00637     "     Defines a linear filter about each voxel of radius 'rmm' mm.\n"
00638     "     The filter weights are proportional to the expression evaluated\n"
00639     "     at each voxel offset in the rmm neighborhood.  You can use only\n"
00640     "     these symbols in the expression:\n"
00641     "         r = radius from center\n"
00642     "         x = dataset x-axis offset from center\n"
00643     "         y = dataset y-axis offset from center\n"
00644     "         z = dataset z-axis offset from center\n"
00645     "         i = x-axis index offset from center\n"
00646     "         j = y-axis index offset from center\n"
00647     "         k = z-axis index offset from center\n"
00648     "     Example:\n"
00649     "       -1filter_expr 12.0 'exp(-r*r/36.067)'\n"
00650     "     This does a Gaussian filter over a radius of 12 mm.  In this\n"
00651     "     example, the FWHM of the filter is 10 mm. [in general, the\n"
00652     "     denominator in the exponent would be 0.36067 * FWHM * FWHM.\n"
00653     "     This is the only way to get a Gaussian blur combined with the\n"
00654     "     -1fmask option.  The radius rmm=12 is chosen where the weights\n"
00655     "     get smallish.]  Another example:\n"
00656     "       -1filter_expr 20.0 'exp(-(x*x+16*y*y+z*z)/36.067)'\n"
00657     "     which is a non-spherical Gaussian filter.\n"
00658     "\n"
00659     "  The following option lets you apply a 'Winsor' filter to the data:\n"
00660     "\n"
00661     "  -1filter_winsor rmm nw\n"
00662     "     The data values within the radius rmm of each voxel are sorted.\n"
00663     "     Suppose there are 'N' voxels in this group.  We index the\n"
00664     "     sorted voxels as s[0] <= s[1] <= ... <= s[N-1], and we call the\n"
00665     "     value of the central voxel 'v' (which is also in array s[]).\n"
00666     "                 If v < s[nw]    , then v is replaced by s[nw]\n"
00667     "       otherwise If v > s[N-1-nw], then v is replace by s[N-1-nw]\n"
00668     "       otherwise v is unchanged\n"
00669     "     The effect is to increase 'too small' values up to some\n"
00670     "     middling range, and to decrease 'too large' values.\n"
00671     "     If N is odd, and nw=(N-1)/2, this would be a median filter.\n"
00672     "     In practice, I recommend that nw be about N/4; for example,\n"
00673     "       -dxyz=1 -1filter_winsor 2.5 19\n"
00674     "     is a filter with N=81 that gives nice results.\n"
00675     "   N.B.: This option is NOT affected by -1fmask\n"
00676     "   N.B.: This option is slow!\n"
00677     "\n"
00678     "MERGING OPTIONS APPLIED TO FORM THE OUTPUT DATASET:\n"
00679     " [That is, different ways to combine results. The]\n"
00680     " [following '-g' options are mutually exclusive! ]\n"
00681     "  -gmean     = Combine datasets by averaging intensities\n"
00682     "                 (including zeros) -- this is the default\n"
00683     "  -gnzmean   = Combine datasets by averaging intensities\n"
00684     "                 (not counting zeros)\n"
00685     "  -gmax      = Combine datasets by taking max intensity\n"
00686     "                 (e.g., -7 and 2 combine to 2)\n"
00687     "  -gamax     = Combine datasets by taking max absolute intensity\n"
00688     "                 (e.g., -7 and 2 combine to 7)\n"
00689     "  -gsmax     = Combine datasets by taking max signed intensity\n"
00690     "                 (e.g., -7 and 2 combine to -7)\n"
00691     "  -gcount    = Combine datasets by counting number of 'hits' in\n"
00692     "                  each voxel (see below for defintion of 'hit')\n"
00693     "  -gorder    = Combine datasets in order of input:\n"
00694     "                * If a voxel is nonzero in dataset #1, then\n"
00695     "                    that value goes into the voxel.\n"
00696     "                * If a voxel is zero in dataset #1 but nonzero\n"
00697     "                    in dataset #2, then the value from #2 is used.\n"
00698     "                * And so forth: the first dataset with a nonzero\n"
00699     "                    entry in a given voxel 'wins'\n"
00700     "  -gfisher   = Takes the arctanh of each input, averages these,\n"
00701     "                  and outputs the tanh of the average.  If the input\n"
00702     "                  datum is 'short', then input values are scaled by\n"
00703     "                  0.0001 and output values by 10000.  This option\n"
00704     "                  is for merging bricks of correlation coefficients.\n"
00705     "\n"
00706     "  -nscale    = If the output datum is shorts, don't do the scaling\n"
00707     "                  to the max range [similar to 3dcalc's -nscale option]\n"
00708     "\n"
00709     "MERGING OPERATIONS APPLIED TO THE THRESHOLD DATA:\n"
00710     " [That is, different ways to combine the thresholds.  If none of these ]\n"
00711     " [are given, the thresholds will not be merged and the output dataset  ]\n"
00712     " [will not have threshold data attached.  Note that the following '-tg']\n"
00713     " [command line options are mutually exclusive, but are independent of  ]\n"
00714     " [the '-g' options given above for merging the intensity data values.  ]\n"
00715     "  -tgfisher  = This option is only applicable if each input dataset\n"
00716     "                  is of the 'fico' or 'fith' types -- functional\n"
00717     "                  intensity plus correlation or plus threshold.\n"
00718     "                  (In the latter case, the threshold values are\n"
00719     "                  interpreted as correlation coefficients.)\n"
00720     "                  The correlation coefficients are averaged as\n"
00721     "                  described by -gfisher above, and the output\n"
00722     "                  dataset will be of the fico type if all inputs\n"
00723     "                  are fico type; otherwise, the output datasets\n"
00724     "                  will be of the fith type.\n"
00725     "         N.B.: The difference between the -tgfisher and -gfisher\n"
00726     "                  methods is that -tgfisher applies to the threshold\n"
00727     "                  data stored with a dataset, while -gfisher\n"
00728     "                  applies to the intensity data.  Thus, -gfisher\n"
00729     "                  would normally be applied to a dataset created\n"
00730     "                  from correlation coefficients directly, or from\n"
00731     "                  the application of the -1thtoin option to a fico\n"
00732     "                  or fith dataset.\n"
00733     "\n"
00734     "OPTIONAL WAYS TO POSTPROCESS THE COMBINED RESULTS:\n"
00735     " [May be combined with the above methods.]\n"
00736     " [Any combination of these options may be used.]\n"
00737     "  -ghits count     = Delete voxels that aren't !=0 in at least\n"
00738     "                       count datasets (!=0 is a 'hit')\n"
00739     "  -gclust rmm vmul = Form clusters with connection distance rmm\n"
00740     "                       and clip off data not in clusters of\n"
00741     "                       volume at least vmul microliters\n"
00742     "\n"
00743     "The '-g' and '-tg' options apply to the entire group of input datasets.\n"
00744     "\n"
00745 
00746     "OPTIONS THAT CONTROL THE NAMES OF THE OUTPUT DATASET:\n"
00747     "  -session dirname  = write output into given directory (default=./)\n"
00748     "  -prefix  pname    = use 'pname' for the output directory prefix\n"
00749     "                       (default=mrg)\n"
00750 #if 0
00751     "  -label   string   = use 'string' for the label in the output\n"
00752     "                       dataset (the label is used for switching\n"
00753     "                       between datasets in AFNI)\n"
00754 #endif
00755     "\n"
00756 
00757     "NOTES:\n"
00758     " **  If only one dataset is read into this program, then the '-g'\n"
00759     "       options do not apply, and the output dataset is simply the\n"
00760     "       '-1' options applied to the input dataset (i.e., edited).\n"
00761     " **  A merged output dataset is ALWAYS of the intensity-only variety.\n"
00762     " **  You can combine the outputs of 3dmerge with other sub-bricks\n"
00763     "       using the program 3dbucket.\n"
00764     " **  Complex-valued datasets cannot be merged.\n"
00765     " **  This program cannot handle time-dependent datasets without -doall.\n"
00766     " **  Note that the input datasets are specified by their .HEAD files,\n"
00767     "       but that their .BRIK files must exist also!\n"
00768 
00769 #ifdef ALLOW_SUBV
00770     "\n"
00771     MASTER_SHORTHELP_STRING
00772     "\n"
00773     " ** Input datasets using sub-brick selectors are treated as follows:\n"
00774     "      - 3D+time if the dataset is 3D+time and more than 1 brick is chosen\n"
00775     "      - otherwise, as bucket datasets (-abuc or -fbuc)\n"
00776     "       (in particular, fico, fitt, etc. datasets are converted to fbuc)\n"
00777     " ** If you are NOT using -doall, and choose more than one sub-brick\n"
00778     "     with the selector, then you may need to use -1dindex to further\n"
00779     "     pick out the sub-brick on which to operate (why you would do this\n"
00780     "     I cannot fathom).  If you are also using a thresholding operation\n"
00781     "     (e.g., -1thresh), then you also MUST use -1tindex to choose which\n"
00782     "     sub-brick counts as the 'threshold' value.  When used with sub-brick\n"
00783     "     selection, 'index' refers the dataset AFTER it has been read in:\n"
00784     "          -1dindex 1 -1tindex 3 'dset+orig[4..7]'\n"
00785     "     means to use the #5 sub-brick of dset+orig as the data for merging\n"
00786     "     and the #7 sub-brick of dset+orig as the threshold values.\n"
00787     " ** The above example would better be done with\n"
00788     "          -1tindex 1 'dset+orig[5,7]'\n"
00789     "     since the default data index is 0. (You would only use -1tindex if\n"
00790     "     you are actually using a thresholding operation.)\n"
00791     " ** -1dindex and -1tindex apply to all input datasets.\n"
00792 #endif
00793    ) ;
00794    exit(0) ;
00795 }
00796 
00797 
00798 
00799 int main( int argc , char * argv[] )
00800 {
00801    int file_num , first_file , nx,ny,nz , nxyz , ii , num_dset ,
00802        file_count , ptmin , iclu,nclu , edit_type , ival,ivout , tval ;
00803    float dx,dy,dz , fac , dxyz , rmm,vmul ;
00804    THD_3dim_dataset * dset=NULL , * new_dset=NULL ;
00805    THD_3dim_dataset ** dsetar=NULL ;                 
00806    short * gnum=NULL ;
00807    float * gfim=NULL , * tfim=NULL , * ggfim=NULL , * ttfim=NULL ;
00808    int     datum ;
00809    MCW_cluster_array * clar ;
00810    float fimfac , fimfacinv , first_fimfac , thrfac ;
00811    int   output_datum , output_thdatum ;
00812    int   input_datum  , input_thdatum , first_datum ;
00813 
00814    float thr_stataux[MAX_STAT_AUX] ;
00815    int   num_fico ;
00816    int   is_int=1 ;   
00817 
00818    int iv, iv_bot, iv_top;      
00819 
00820    
00821    printf ("\n\nProgram %s \n", PROGRAM_NAME);
00822    printf ("Last revision: %s \n\n", LAST_MOD_DATE);
00823 
00824    
00825 
00826    if( argc < 2 || strncmp(argv[1],"-help",4) == 0 ) MRG_Syntax() ;
00827 
00828    
00829 
00830    mainENTRY("3dmerge main") ; machdep() ; PRINT_VERSION("3dmerge") ;
00831 
00832    { int new_argc ; char ** new_argv ;
00833      addto_args( argc , argv , &new_argc , &new_argv ) ;
00834      if( new_argv != NULL ){ argc = new_argc ; argv = new_argv ; }
00835    }
00836 
00837    AFNI_logger("3dmerge",argc,argv) ;
00838 
00839    first_file = MRG_read_opts( argc , argv ) ;
00840    file_count = argc - first_file ;            
00841 
00842    if( ! MRG_be_quiet )
00843       printf("3dmerge: edit and combine 3D datasets, by RW Cox\n") ;
00844 
00845    if( first_file < 1 || first_file >= argc ){
00846       fprintf(stderr,"*** ILLEGAL COMMAND LINE ***\n") ; exit(1) ;
00847    }
00848 
00849     
00850    if (MRG_doall)
00851      { int nerr = 0 ;
00852 
00853        if( MRG_ivfim >= 0 ){   
00854          fprintf(stderr,"-1dindex is not compatible with -doall option \n");
00855          nerr++ ;  }
00856        if( MRG_ivthr >= 0 ){   
00857          fprintf(stderr,"-1dindex is not compatible with -doall option \n");
00858          nerr++ ;  }
00859 
00860        if (MRG_edopt.thtoin > 0)  {
00861          fprintf (stderr, "-1thtoin is not compatible with -doall option \n");
00862          nerr++ ;  }
00863        if (MRG_edopt.thresh > 0.0)  {
00864          fprintf (stderr, "-1thresh is not compatible with -doall option \n");
00865          nerr++ ;  }
00866        if (MRG_edopt.thrfilter_opt > 0)  {
00867          fprintf (stderr, "-t1filter is not compatible with -doall option \n");
00868          nerr++ ;  }
00869        if (MRG_edopt.thrblur > 0.0)  {
00870          fprintf (stderr, "-t1blur is not compatible with -doall option \n");
00871          nerr++ ;  }
00872        if (MRG_thdatum >= 0)  {
00873          fprintf (stderr, "-thdatum is not compatible with -doall option \n");
00874          nerr++ ;  }
00875        if (MRG_keepthr)  {
00876          fprintf (stderr, "-keepthr is not compatible with -doall option \n");
00877          nerr++ ;  }
00878        if (MRG_cflag_gthr > 0)  {
00879          fprintf (stderr, "-tgfisher is not compatible with -doall option \n");
00880          nerr++ ;  }
00881 
00882        if( nerr > 0 ) exit(1) ;
00883      }
00884 
00885    
00886 
00887    if( (MRG_ivfim >= 0 || MRG_ivthr >=0) && MRG_keepthr ){
00888       fprintf(stderr,"-keepthr is not compatible with -1dindex or -1tindex\n") ;
00889       exit(1) ;
00890    }
00891 
00892    if( (MRG_ivfim >= 0 || MRG_ivthr >=0) && MRG_cflag_gthr ){
00893       fprintf(stderr,"-tgfisher is not compatible with -1dindex or -1tindex\n") ;
00894       exit(1) ;
00895    }
00896 
00897       
00898    for (file_num = first_file;  file_num < argc;  file_num++)
00899      {
00900        dset = DSET_OPEN( argv[file_num] ) ;
00901        if( ! ISVALID_3DIM_DATASET(dset) )
00902          {
00903            fprintf(stderr,"*** cannot open dataset %s\n",argv[file_num]) ;
00904            exit(1) ;
00905          }
00906 
00907        
00908 
00909        if( MRG_ivfim >= DSET_NVALS(dset) ){
00910           fprintf(stderr,
00911                   "*** Dataset %s does not have enough bricks for -1dindex %d\n" ,
00912                   argv[file_num],MRG_ivfim) ;
00913           exit(1) ;
00914        }
00915        if( MRG_ivthr >= DSET_NVALS(dset) ){
00916           fprintf(stderr,
00917                   "*** Dataset %s does not have enough bricks for -1tindex %d\n" ,
00918                   argv[file_num],MRG_ivthr) ;
00919           exit(1) ;
00920        }
00921 
00922        THD_delete_3dim_dataset( dset , False ) ; dset = NULL ;
00923      }
00924 
00925    
00926 
00927    if( MRG_ivfim < 0 ) fprintf(stderr,"++ default -1dindex = 0\n") ;
00928    if( MRG_ivthr < 0 ) fprintf(stderr,"++ default -1tindex = 1\n") ;
00929 
00930    
00931 
00932    dset = DSET_OPEN( argv[first_file] ) ;
00933    if( ! ISVALID_3DIM_DATASET(dset) ){
00934       fprintf(stderr,"*** Unable to open first dataset %s\n",argv[first_file]) ;
00935       exit(1) ;
00936    }
00937 
00938    if( DSET_NUM_TIMES(dset) > 1 && (!MRG_doall && MRG_ivfim < 0) ){
00939       fprintf(stderr, "*** Unable to merge time-dependent datasets"
00940                       " without -doall or -1dindex\n") ;
00941       exit(1) ;
00942    }
00943 
00944    
00945 
00946    nx = dset->daxes->nxx ;
00947    ny = dset->daxes->nyy ;
00948    nz = dset->daxes->nzz ; nxyz = nx*ny*nz ;
00949 
00950    dx = fabs(dset->daxes->xxdel) ;
00951    dy = fabs(dset->daxes->yydel) ;
00952    dz = fabs(dset->daxes->zzdel) ;
00953 
00954    if( MRG_edopt.fake_dxyz ) dx = dy = dz = 1.0 ;  
00955 
00956    nice(1) ;  
00957 
00958    if( MRG_edopt.nfmask > 0 && MRG_edopt.nfmask != nxyz ){
00959       fprintf(stderr,
00960               "*** -1fmask and 1st dataset don't have same number of voxels\n\a");
00961       exit(1) ;
00962    }
00963 
00964    
00965    
00966    
00967 
00968    if( file_count == 1 ){
00969 
00970       ival        = DSET_PRINCIPAL_VALUE(dset) ;
00971       input_datum = DSET_BRICK_TYPE(dset,ival) ;
00972       if( MRG_datum >= 0 ) output_datum = MRG_datum ;
00973       else                 output_datum = input_datum ;
00974 
00975 
00976 
00977 
00978 
00979 
00980 
00981 
00982       new_dset = EDIT_empty_copy( dset ) ;
00983 
00984       EDIT_dset_items( new_dset ,
00985                           ADN_prefix         , MRG_output_prefix ,
00986                           ADN_directory_name , MRG_output_session ,
00987                        ADN_none ) ;
00988 
00989       if( THD_is_file(new_dset->dblk->diskptr->header_name) ){
00990          fprintf(stderr,
00991                  "*** Output file %s already exists -- cannot continue!\n",
00992                  new_dset->dblk->diskptr->header_name ) ;
00993          exit(1) ;
00994       }
00995 
00996       THD_delete_3dim_dataset( new_dset , False ) ;  
00997 
00998       
00999 
01000       if( MRG_keepthr && !ISFUNC(dset) ){
01001         fprintf(stderr,"*** -keepthr can't be used on non-functional dataset!\n");
01002         exit(1) ;
01003       }
01004       if( MRG_keepthr && dset->func_type == FUNC_FIM_TYPE ){
01005         fprintf(stderr,"*** -keepthr can't be used on 'fim' type dataset!\n") ;
01006         exit(1) ;
01007       }
01008       if( MRG_keepthr && dset->func_type == FUNC_BUCK_TYPE ){
01009         fprintf(stderr,"*** -keepthr can't be used on 'fbuc' type dataset!\n"
01010                        "    You can use '3dbuc2fim' first, if needed.\n"    );
01011         exit(1) ;
01012       }
01013  
01014 
01015 
01016       if( ! MRG_be_quiet ){
01017          printf("-- editing input dataset in memory (%.1f MB)\n",
01018                 ((double)dset->dblk->total_bytes) / MEGA ) ;
01019          fflush(stdout) ;
01020       }
01021 
01022   
01023   if (MRG_doall)
01024     {  iv_bot = 0;  iv_top = DSET_NVALS(dset);  }
01025   else if( MRG_ivfim >= 0 )                       
01026     {  iv_bot = MRG_ivfim ; iv_top = iv_bot+1 ; }
01027   else
01028     {  iv_bot = DSET_PRINCIPAL_VALUE(dset);  iv_top = iv_bot + 1;  }
01029 
01030   
01031   for (iv = iv_bot;  iv < iv_top;  iv++)
01032     {
01033       if ((!MRG_be_quiet) && MRG_doall) printf ("Editing sub-brick %d\n", iv);
01034 
01035       MRG_edopt.iv_fim = iv;
01036 
01037       EDIT_one_dataset( dset , &MRG_edopt ) ;  
01038 
01039       if( !MRG_be_quiet && !MRG_doall ){ printf(".") ; fflush(stdout) ; }
01040     }
01041 
01042    if( MRG_edopt.nfmask > 0 ){
01043      free(MRG_edopt.fmask) ; MRG_edopt.fmask = NULL ; MRG_edopt.nfmask = 0 ;
01044    }
01045 
01046     if( !MRG_be_quiet && !MRG_doall ) printf("\n") ;
01047 
01048 
01049 
01050       new_dset = EDIT_empty_copy( dset ) ;
01051 
01052       tross_Copy_History( dset , new_dset ) ;
01053       tross_Make_History( "3dmerge" , argc , argv , new_dset ) ;
01054 
01055       EDIT_dset_items( new_dset ,
01056                           ADN_prefix , MRG_output_prefix ,
01057                           ADN_label1 , MRG_output_prefix ,
01058                           ADN_directory_name , MRG_output_session ,
01059                        ADN_none ) ;
01060       strcat( new_dset->self_name , "(ED)" ) ;
01061                                                            
01062       if( (! MRG_keepthr) && (new_dset->dblk->nvals > 1) && (! MRG_doall) )
01063          EDIT_dset_items( new_dset ,
01064                              ADN_nvals , 1 ,
01065                              ADN_ntt   , 0 ,                 
01066                              ADN_func_type , FUNC_FIM_TYPE ,
01067                           ADN_none ) ;
01068 
01069       if( MRG_keepthr && ISFUNC(new_dset) && FUNC_HAVE_THR(new_dset->func_type) ){
01070          ii            = FUNC_ival_thr[dset->func_type] ;
01071          input_thdatum = DSET_BRICK_TYPE(dset,ii) ;
01072          if( MRG_thdatum >= 0 ) output_thdatum = MRG_thdatum ;
01073          else                   output_thdatum = input_thdatum ;
01074       } else {
01075          output_thdatum = input_thdatum = ILLEGAL_TYPE ;
01076       }
01077 
01078 
01079 
01080   
01081   for (iv = iv_bot;  iv < iv_top;  iv++)
01082     {
01083   
01084   if (MRG_doall)
01085     {
01086       ival  = iv;
01087       ivout = iv;
01088     }
01089   else if( MRG_ivfim >= 0 )
01090     {
01091       ival  = MRG_ivfim ;
01092       ivout = DSET_PRINCIPAL_VALUE(new_dset) ;
01093     }
01094   else
01095     {
01096       ival  = DSET_PRINCIPAL_VALUE(dset) ;
01097       ivout = DSET_PRINCIPAL_VALUE(new_dset) ;
01098     }
01099 
01100       if( input_datum == output_datum ){
01101 
01102 
01103 
01104 
01105          mri_fix_data_pointer( DSET_ARRAY(dset,ival) , DSET_BRICK(new_dset,ivout) ) ;
01106 
01107 #if 1
01108 #   if 0
01109          if( ivout != ival )
01110 #   endif
01111             DSET_BRICK_FACTOR(new_dset,ivout) = DSET_BRICK_FACTOR(dset,ival) ;
01112 #endif
01113 
01114       } else {
01115 
01116 
01117 
01118          void * dfim , * efim ;
01119          float efac = DSET_BRICK_FACTOR(dset,ival) ;
01120 
01121          if( ! MRG_be_quiet ){
01122             printf("-- coercing output datum to be %s\n",
01123                    MRI_TYPE_name[output_datum]);
01124          }
01125 
01126          efim = DSET_ARRAY(dset,ival) ;
01127          dfim = (void *) malloc( mri_datum_size(output_datum) * nxyz ) ;
01128          if( dfim == NULL ){
01129             fprintf(stderr,"*** Can't malloc output brick #%d\n",ivout); exit(1);
01130          }
01131 
01132 
01133 
01134          if( MRI_IS_INT_TYPE(output_datum) ){
01135             fimfac = EDIT_coerce_autoscale( nxyz , input_datum  , efim ,
01136                                                    output_datum , dfim  ) ;
01137             if( fimfac == 0.0 ) fimfac  = 1.0 ;
01138             if( efac   != 0.0 ) fimfac /= efac ;
01139 
01140             DSET_BRICK_FACTOR(new_dset,ivout) = (fimfac != 0.0 && fimfac != 1.0)
01141                                                 ? 1.0/fimfac : 0.0 ;
01142          } else {
01143 
01144             EDIT_coerce_scale_type( nxyz , efac , input_datum  , efim ,
01145                                                   output_datum , dfim  ) ;
01146             DSET_BRICK_FACTOR(new_dset,ivout) = 0.0 ;
01147          }
01148 
01149          mri_free( DSET_BRICK(dset,ival) ) ;
01150          EDIT_substitute_brick( new_dset , ivout , output_datum , dfim ) ;
01151       }
01152 
01153 
01154 
01155       if( output_thdatum >= 0 ){
01156 
01157          ival  = FUNC_ival_thr[    dset->func_type] ;
01158          ivout = FUNC_ival_thr[new_dset->func_type] ;
01159 
01160          if( input_thdatum == output_thdatum ){
01161 
01162             mri_fix_data_pointer( DSET_ARRAY(dset,ival),DSET_BRICK(new_dset,ivout) ) ;
01163 
01164 #if 0
01165             DSET_BRICK_FACTOR(new_dset,ivout) = DSET_BRICK_FACTOR(dset,ival) ;
01166 #endif
01167 
01168          } else {
01169             void * dfim , * efim ;
01170 
01171             if( ! MRG_be_quiet ){
01172                printf("-- coercing threshold datum to be %s\n",
01173                       MRI_TYPE_name[output_thdatum]);
01174             }
01175 
01176             efim = DSET_ARRAY(dset,ival) ;
01177             dfim = (void *) XtMalloc( mri_datum_size(output_thdatum) * nxyz ) ;
01178 
01179             switch( output_thdatum ){
01180                default: fprintf(stderr,"** illegal output_thdatum = %d\n",
01181                                 output_thdatum);
01182                exit(1) ;
01183 
01184                case MRI_float:
01185                   fimfacinv = 0.0 ;
01186                   fimfac    = DSET_BRICK_FACTOR(dset,ival) ;
01187                   if( fimfac == 0.0 ){
01188                      fimfac = (input_thdatum == MRI_short)
01189                                ? 1.0/FUNC_scale_short[dset->func_type]
01190                                : (input_thdatum == MRI_byte)
01191                                ? 1.0/FUNC_scale_byte[dset->func_type] : 0.0 ;
01192                   }
01193                break ;
01194 
01195                case MRI_short:
01196                   if( input_datum == MRI_float ){
01197                      fimfac    = FUNC_scale_short[new_dset->func_type] ;
01198                      fimfacinv = 1.0 / fimfac ;
01199                   } else if( input_datum == MRI_byte ){
01200                      fimfac    = ((float)FUNC_scale_short[new_dset->func_type])
01201                                 / FUNC_scale_byte[new_dset->func_type] ;
01202                      fimfacinv = 1.0 / FUNC_scale_short[new_dset->func_type] ;
01203                   } else {
01204                      fprintf(stderr,"** illegal input_thdatum = %d\n",input_thdatum);
01205                      exit(1) ;
01206                   }
01207                break ;
01208 
01209                case MRI_byte:
01210                   if( input_datum == MRI_float ){
01211                      fimfac    = FUNC_scale_byte[new_dset->func_type] ;
01212                      fimfacinv = 1.0 / fimfac ;
01213                   } else if( input_datum == MRI_short ){
01214                      fimfac    = ((float)FUNC_scale_byte[new_dset->func_type])
01215                                 / FUNC_scale_short[new_dset->func_type] ;
01216                      fimfacinv = 1.0 / FUNC_scale_byte[new_dset->func_type] ;
01217                   } else {
01218                      fprintf(stderr,"** illegal input_thdatum = %d\n",input_thdatum);
01219                      exit(1) ;
01220                   }
01221                break ;
01222             }
01223 
01224             EDIT_coerce_scale_type( nxyz , fimfac ,
01225                                     DSET_BRICK_TYPE(dset,ival),efim ,
01226                                     output_thdatum,dfim ) ;
01227 
01228             DSET_BRICK_FACTOR(new_dset,ivout) = fimfacinv ;
01229             EDIT_substitute_brick( new_dset , ivout , output_thdatum , dfim ) ;
01230             mri_free( DSET_BRICK(dset,ival) ) ;
01231          }
01232       }
01233 
01234     }  
01235 
01236 
01237       THD_load_statistics( new_dset ) ;
01238       THD_write_3dim_dataset( NULL,NULL , new_dset , True ) ;
01239       if( ! MRG_be_quiet )
01240         fprintf(stderr,"-- Wrote edited dataset: %s\n" , DSET_BRIKNAME(new_dset) ) ;
01241       exit(0) ;
01242    }
01243 
01244    
01245    
01246 
01247    
01248 
01249    dsetar = (THD_3dim_dataset **) malloc(sizeof(THD_3dim_dataset *)*file_count);
01250    for( ii=0 ; ii < file_count ; ii++ ) dsetar[ii] = NULL ;
01251    dsetar[0] = dset ;
01252 
01253    
01254 
01255    new_dset = EDIT_empty_copy( dset ) ;
01256    ival     = DSET_PRINCIPAL_VALUE(dset) ;
01257 
01258    if( MRG_datum >= 0 ) output_datum = MRG_datum ;
01259    else                 output_datum = DSET_BRICK_TYPE(dset,ival) ;
01260 
01261    EDIT_dset_items( new_dset ,
01262                        ADN_prefix , MRG_output_prefix ,
01263                        ADN_label1 , MRG_output_prefix ,
01264                        ADN_directory_name , MRG_output_session ,
01265                     ADN_none ) ;
01266    strcat( new_dset->self_name , "(MG)" ) ;
01267 
01268    
01269 
01270   if (! MRG_doall)   
01271    switch( MRG_cflag_gthr ){
01272        default:
01273           EDIT_dset_items( new_dset , ADN_nvals,1 , ADN_ntt,0 , ADN_none ) ;
01274           if( ISFUNC(dset) )
01275              EDIT_dset_items( new_dset , ADN_func_type,FUNC_FIM_TYPE , ADN_none ) ;
01276        break ;
01277 
01278        case THFLAG_FICO:  
01279           num_fico = 0 ;
01280        break ;
01281    }
01282 
01283    if( THD_is_file(new_dset->dblk->diskptr->header_name) ){
01284       fprintf(stderr,
01285               "*** Output file %s already exists -- cannot continue!\n",
01286               new_dset->dblk->diskptr->header_name ) ;
01287       exit(1) ;
01288    }
01289 
01290    if( ! MRG_be_quiet && MRG_keepthr )
01291       printf("-- ignoring -keepthr option\n") ;
01292 
01293 
01294   
01295    if (MRG_doall)
01296      {  iv_bot = 0;  iv_top = DSET_NVALS(dset);  }
01297    else if( MRG_ivfim >= 0 )                       
01298      {  iv_bot = MRG_ivfim ; iv_top = iv_bot+1 ; }
01299    else
01300      {  iv_bot = DSET_PRINCIPAL_VALUE(dset);  iv_top = iv_bot + 1;  }
01301 
01302   
01303 
01304   ivout = 0 ;  
01305 
01306   for (iv = iv_bot;  iv < iv_top;  iv++)
01307     {
01308       if ((!MRG_be_quiet) ) printf ("-- Editing sub-brick %d \n", iv);
01309 
01310       MRG_edopt.iv_fim = iv;
01311 
01312    
01313 
01314    tfim = (float *) XtMalloc( sizeof(float) * nxyz ) ;  
01315    gfim = (float *) XtMalloc( sizeof(float) * nxyz ) ;  
01316    gnum = (short *) XtMalloc( sizeof(short) * nxyz ) ;  
01317    for( ii=0 ; ii < nxyz ; ii++ ) gfim[ii] = 0.0 ;      
01318    for( ii=0 ; ii < nxyz ; ii++ ) gnum[ii] = 0 ;
01319 
01320    
01321 
01322    if( MRG_cflag_gthr != THFLAG_NONE ){
01323       ttfim = (float *) XtMalloc( sizeof(float) * nxyz ) ;  
01324       ggfim = (float *) XtMalloc( sizeof(float) * nxyz ) ;  
01325       for( ii=0 ; ii < nxyz ; ii++ ) ggfim[ii] = 0.0 ;      
01326 
01327       for( ii=0 ; ii < MAX_STAT_AUX ; ii++ ) thr_stataux[ii] = 0 ;
01328    }
01329 
01330    if( ! MRG_be_quiet ){
01331       float nbytes = (2.0*sizeof(float)+sizeof(short))*nxyz ;
01332       if( MRG_cflag_gthr != THFLAG_NONE ) nbytes += 2.0*sizeof(float)*nxyz ;
01333       printf("-- allocated %.1f MB scratch memory\n", nbytes/MEGA ) ;
01334    }
01335 
01336    
01337 
01338    num_dset = 0 ;
01339    for( file_num=first_file; file_num < argc ; file_num++ ){
01340 
01341 
01342 
01343       dset = dsetar[ file_num - first_file ] ;  
01344       if( dset == NULL ){
01345          dset = dsetar[ file_num - first_file ] = DSET_OPEN( argv[file_num] ) ;
01346          if( ! ISVALID_3DIM_DATASET(dset) ){
01347            fprintf(stderr,"*** cannot open dataset %s\n",argv[file_num]); exit(1);
01348          }
01349       }
01350 
01351       
01352 
01353       if( dset->daxes->nxx != nx ||
01354           dset->daxes->nyy != ny || dset->daxes->nzz != nz ){
01355 
01356          fprintf(stderr,"*** dataset brick size mismatch at file %s\n",
01357                  argv[file_num] ) ;
01358          exit(1) ;
01359       }
01360 
01361       
01362       if ( (MRG_doall) && (DSET_NVALS(dset) != iv_top) )
01363          fprintf (stderr, "*** -doall dataset nvals mismatch at file %s\n",
01364                   argv[file_num]);
01365 
01366 
01367       if( DSET_NUM_TIMES(dset) > 1 && (!MRG_doall && MRG_ivfim < 0) ){ 
01368          fprintf(stderr,                                               
01369                  "*** cannot use time-dependent dataset %s"
01370                  " without -doall or -1dindex\n",argv[file_num]) ;
01371          exit(1) ;
01372       }
01373 
01374       
01375 
01376       if( MRG_cflag_gthr == THFLAG_FICO ){
01377 
01378          if( !ISFUNC(dset) ){
01379             fprintf(stderr,
01380                   "*** dataset from file %s is anatomical using '-tgfisher'!\n",
01381                 argv[file_num] ) ;
01382             exit(1) ;
01383          }
01384 
01385          switch( dset->func_type ){
01386             default:
01387                fprintf(stderr,
01388                 "*** dataset from file %s is illegal type using '-tgfisher'!\n",
01389                    argv[file_num] ) ;
01390             exit(1) ;
01391 
01392             case FUNC_COR_TYPE:   
01393                num_fico ++ ;
01394                for( ii=0 ; ii < FUNC_need_stat_aux[FUNC_COR_TYPE] ; ii++ )
01395                  thr_stataux[ii] += dset->stat_aux[ii] ;
01396             break ;
01397 
01398             case FUNC_THR_TYPE:  
01399             break ;
01400          }
01401       }
01402 
01403       
01404 
01405 #if 1
01406       ival = iv ;                  
01407 #else
01408       if (MRG_doall)  ival = iv;   
01409       else            ival = DSET_PRINCIPAL_VALUE(dset) ;
01410 #endif
01411       datum = DSET_BRICK_TYPE(dset,ival) ;
01412 
01413       if( ! AFNI_GOOD_FUNC_DTYPE(datum) ){
01414          fprintf(stderr,"*** Illegal datum for 3dmerge: %s in file %s ***\n" ,
01415                  MRI_TYPE_name[datum] , argv[file_num] ) ;
01416          exit(1) ;
01417       }
01418 
01419       if( ! MRG_be_quiet ){
01420          printf("-- processing file %s" , argv[file_num] ) ;
01421          fflush(stdout) ;
01422       }
01423 
01424       
01425 
01426       if( MRG_have_edopt )
01427          EDIT_one_dataset( dset , &MRG_edopt ) ;  
01428       else
01429          THD_load_datablock( dset->dblk ) ;
01430 
01431       
01432 
01433       if( !DSET_LOADED(dset) ){
01434          fprintf(stderr,"** Can't get data from %s\n",DSET_BRIKNAME(dset)) ;
01435          exit(1) ;
01436       }
01437 
01438       if( ! MRG_be_quiet ){ printf(".") ; fflush(stdout) ; }
01439 
01440       
01441 
01442       fimfac = DSET_BRICK_FACTOR(dset,ival) ;          
01443 
01444       if( MRG_cflag_g == CFLAG_FISHER             &&   
01445           DSET_BRICK_TYPE(dset,ival) == MRI_short &&
01446           (fimfac==0.0 || fimfac==1.0)              ){
01447 
01448          fimfac = 1.0 / FUNC_COR_SCALE_SHORT ;
01449       }
01450 
01451       if( num_dset == 0 ){
01452          first_fimfac = fimfac ;  
01453          first_datum  = datum  ;
01454       }
01455 
01456 
01457 
01458       is_int = is_int && (MRI_IS_INT_TYPE(datum) && fimfac == 0.0) ;
01459 
01460       
01461 
01462       EDIT_coerce_scale_type( nxyz , fimfac ,
01463                               DSET_BRICK_TYPE(dset,ival) , DSET_ARRAY(dset,ival) ,
01464                               MRI_float , tfim ) ;
01465 
01466       
01467 
01468       if( MRG_cflag_gthr != THFLAG_NONE && (tval=DSET_THRESH_VALUE(dset)) >= 0 ){
01469 
01470          int thdatum = DSET_BRICK_TYPE(dset,tval) ;
01471 
01472          if( ! AFNI_GOOD_FUNC_DTYPE(thdatum) ){
01473             fprintf(stderr,"*** Illegal threshold for 3dmerge: %s in file %s ***\n" ,
01474                     MRI_TYPE_name[thdatum] , argv[file_num] ) ;
01475             exit(1) ;
01476          }
01477 
01478          thrfac = DSET_BRICK_FACTOR(dset,tval) ;          
01479 
01480          if( MRG_cflag_gthr == THFLAG_FICO           &&   
01481              DSET_BRICK_TYPE(dset,tval) == MRI_short &&
01482              (thrfac==0.0 || thrfac==1.0)              ){
01483 
01484             thrfac = 1.0 / FUNC_COR_SCALE_SHORT ;
01485          }
01486 
01487          EDIT_coerce_scale_type( nxyz , thrfac ,
01488                                  thdatum , DSET_ARRAY(dset,tval) ,
01489                                  MRI_float , ttfim ) ;
01490       }
01491 
01492       DSET_unload(dset) ;  
01493 
01494       
01495 
01496       if( MRG_cflag_g == CFLAG_MMAX ){
01497          for( ii=0 ; ii < nxyz ; ii++ ){
01498             if( tfim[ii] != 0 ){
01499                gnum[ii]++ ;
01500                if( tfim[ii] > gfim[ii] ) gfim[ii] = tfim[ii] ;
01501             }
01502          }
01503       } else if( MRG_cflag_g == CFLAG_AMAX ){
01504          float dab ;
01505          for( ii=0 ; ii < nxyz ; ii++ ){
01506             if( tfim[ii] != 0 ){
01507                gnum[ii]++ ;
01508                dab = fabs(tfim[ii]) ;
01509                if( dab > gfim[ii] ) gfim[ii] = dab ;
01510             }
01511          }
01512       } else if( MRG_cflag_g == CFLAG_SMAX ){
01513          float dab ;
01514          for( ii=0 ; ii < nxyz ; ii++ ){
01515             if( tfim[ii] != 0 ){
01516                gnum[ii]++ ;
01517                dab = fabs(tfim[ii]) ;
01518                if( dab > fabs(gfim[ii]) ) gfim[ii] = tfim[ii] ;
01519             }
01520          }
01521       } else if( MRG_cflag_g == CFLAG_ORDER ){
01522          for( ii=0 ; ii < nxyz ; ii++ ){
01523             if( tfim[ii] != 0 ){
01524                gnum[ii]++ ;
01525                if( gfim[ii] == 0 ) gfim[ii] = tfim[ii] ;
01526             }
01527          }
01528       } else if( MRG_cflag_g == CFLAG_FISHER ){
01529          for( ii=0 ; ii < nxyz ; ii++ ){
01530             if( tfim[ii] != 0 ){
01531                gnum[ii]++ ; gfim[ii] += ATANH(tfim[ii]) ;
01532             }
01533          }
01534       } else {                                
01535          for( ii=0 ; ii < nxyz ; ii++ ){
01536             if( tfim[ii] != 0 ){
01537                gnum[ii]++ ; gfim[ii] += tfim[ii] ;
01538             }
01539          }
01540       }
01541 
01542       
01543 
01544       if( MRG_cflag_gthr == THFLAG_FICO ){
01545          for( ii=0 ; ii < nxyz ; ii++ ) ggfim[ii] += ATANH(ttfim[ii]) ;
01546       }
01547 
01548       if( ! MRG_be_quiet ){ printf(".\n") ; fflush(stdout) ; }
01549 
01550       num_dset++ ;
01551    }  
01552 
01553    myXtFree(tfim) ;                      
01554    if( ttfim != NULL ) myXtFree(ttfim) ;
01555 
01556    if( MRG_edopt.nfmask > 0 ){
01557      free(MRG_edopt.fmask) ; MRG_edopt.fmask = NULL ; MRG_edopt.nfmask = 0 ;
01558    }
01559 
01560    
01561 
01562    if( num_dset <= 1 ){
01563       fprintf(stderr,"*** Only found 1 dataset -- computations aborted!\n") ;
01564       exit(1) ;
01565    }
01566 
01567    if( ! MRG_be_quiet ) printf("-- merging results into sub-brick %d\n",ivout) ;
01568 
01569    
01570 
01571 
01572    if( MRG_hits_g > 0 ){
01573       for( ii=0 ; ii < nxyz ; ii++ )
01574          if( gnum[ii] < MRG_hits_g ) { gfim[ii] = 0 ; gnum[ii] = 0 ; }
01575    }
01576 
01577    
01578    
01579 
01580 
01581    switch( MRG_cflag_g ){
01582       default:          is_int = 0 ; break ;   
01583 
01584       case CFLAG_COUNT: is_int = 1 ; break ;   
01585 
01586       case CFLAG_MMAX:                         
01587       case CFLAG_SMAX:                         
01588       case CFLAG_AMAX:                         
01589       case CFLAG_ORDER: break ;                
01590    }
01591 
01592    
01593 
01594    switch( MRG_cflag_g ){
01595       default: break ;
01596 
01597       case CFLAG_COUNT:
01598          first_fimfac = 0.0 ;
01599          for( ii=0 ; ii < nxyz ; ii++ ) gfim[ii] = gnum[ii] ;
01600       break ;
01601 
01602       case CFLAG_MEAN:
01603          fac = 1.0 / num_dset ;
01604          for( ii=0 ; ii < nxyz ; ii++ ) gfim[ii] *= fac ;
01605       break ;
01606 
01607       case CFLAG_NZMEAN:
01608          for( ii=0 ; ii < nxyz ; ii++ )
01609             if( gnum[ii] > 0 ) gfim[ii] /= gnum[ii] ;
01610       break ;
01611 
01612       case CFLAG_FISHER:
01613          fac = 1.0 / num_dset ;
01614          for( ii=0 ; ii < nxyz ; ii++ ) gfim[ii] = TANH( fac * gfim[ii] ) ;
01615       break ;
01616    }
01617 
01618    
01619 
01620    switch( MRG_cflag_gthr ){
01621       default: break ;
01622 
01623       case THFLAG_FICO:
01624          fac = 1.0 / num_dset ;
01625          for( ii=0 ; ii < nxyz ; ii++ ) ggfim[ii] = TANH( fac * ggfim[ii] ) ;
01626       break ;
01627    }
01628 
01629    
01630 
01631 
01632    myXtFree( gnum ) ;
01633 
01634    
01635 
01636    rmm   = MRG_clust_rmm_g ;
01637    vmul  = MRG_clust_vmul_g ;
01638    dxyz  = dx*dy*dz ;
01639    ptmin = vmul / dxyz + 0.99 ;
01640 
01641    if( (rmm >= dx || rmm >= dy || rmm >= dz) && ptmin > 1 ){
01642       if( ! MRG_be_quiet ) printf("-- editing merger for cluster size\n") ;
01643 
01644       clar  = MCW_find_clusters( nx,ny,nz , dx,dy,dz , MRI_float,gfim , rmm ) ;
01645       nclu  = 0 ;
01646       if( clar != NULL ){
01647          for( iclu=0 ; iclu < clar->num_clu ; iclu++ ){
01648             if( clar->clar[iclu] != NULL && clar->clar[iclu]->num_pt < ptmin ){
01649                KILL_CLUSTER(clar->clar[iclu]) ;
01650             } else if( clar->clar[iclu] != NULL ){
01651                nclu++ ;
01652             }
01653          }
01654       }
01655 
01656       if( nclu > 0 ){
01657          for( iclu=0 ; iclu < clar->num_clu ; iclu++ ){
01658             if( clar->clar[iclu] != NULL && clar->clar[iclu]->num_pt > 0 )
01659                MCW_cluster_to_vol( nx,ny,nz , MRI_float,gfim , clar->clar[iclu] ) ;
01660          }
01661       }
01662    }
01663 
01664    
01665 
01666    if( !MRG_doall ){  
01667       for( ii=0 ; ii < nxyz ; ii++ ) if( gfim[ii] != 0 ) break ;
01668       if( ii == nxyz ){
01669          fprintf(stderr,
01670            "*** Merged dataset has no nonzero entries -- will not write\n" ) ;
01671          exit(0) ;
01672       }
01673    }
01674 
01675    
01676    
01677 
01678    switch( output_datum ){
01679 
01680       default:
01681          fprintf(stderr,
01682                  "*** Fatal Error ***\n"
01683                  "*** Somehow ended up with output_datum = %d\n",output_datum) ;
01684       exit(1) ;
01685 
01686       case MRI_complex:{
01687          void * dfim ;
01688          dfim = (void *) XtMalloc( sizeof(complex) * nxyz ) ;
01689          EDIT_coerce_type( nxyz , MRI_float,gfim , MRI_complex,dfim ) ;
01690          myXtFree( gfim ) ;
01691          EDIT_substitute_brick( new_dset , ivout , MRI_complex , dfim ) ;
01692          DSET_BRICK_FACTOR(new_dset,ivout) = 0.0 ;
01693       }
01694       break ;
01695 
01696       case MRI_float:
01697          EDIT_substitute_brick( new_dset , ivout , MRI_float , gfim ) ;
01698          DSET_BRICK_FACTOR(new_dset,ivout) = 0.0 ;
01699       break ;
01700 
01701       case MRI_byte:
01702       case MRI_short:{
01703          void * dfim ;
01704          float gtop ;
01705 
01706          gtop = MCW_vol_amax( nx,ny,nz , MRI_float,gfim ) ;
01707 
01708          if( MRG_cflag_g == CFLAG_FISHER ){
01709             fimfac = FUNC_COR_SCALE_SHORT ;
01710          } else if( gtop == 0.0 ||           
01711                     MRG_nscale  ||           
01712                     (is_int && gtop <= MRI_TYPE_maxval[output_datum]) ){
01713             fimfac = 0.0 ;
01714          } else {
01715             fimfac = MRI_TYPE_maxval[output_datum] / gtop ;
01716          }
01717 
01718          dfim = (void *) XtMalloc( mri_datum_size(output_datum) * nxyz ) ;
01719          EDIT_coerce_scale_type( nxyz,fimfac , MRI_float,gfim , output_datum,dfim ) ;
01720          myXtFree( gfim ) ;
01721          EDIT_substitute_brick( new_dset , ivout , output_datum , dfim ) ;
01722          DSET_BRICK_FACTOR(new_dset,ivout) = (fimfac != 0.0) ? 1.0/fimfac : 0.0 ;
01723       }
01724       break ;
01725    }
01726 
01727 
01728 
01729    if( MRG_cflag_gthr != THFLAG_NONE ){
01730       short * dfim ;
01731 
01732       dfim   = (short *) XtMalloc( sizeof(short) * nxyz ) ;
01733       thrfac = FUNC_COR_SCALE_SHORT ;
01734       EDIT_coerce_scale_type( nxyz,thrfac , MRI_float,ggfim , MRI_short,dfim ) ;
01735       myXtFree( ggfim ) ;
01736       EDIT_substitute_brick( new_dset , DSET_THRESH_VALUE(new_dset) ,
01737                              MRI_short , dfim ) ;
01738       DSET_BRICK_FACTOR(new_dset,1) = 1.0/thrfac ;
01739 
01740       
01741 
01742 
01743       if( num_fico == num_dset ){
01744          (void) EDIT_dset_items( new_dset , ADN_stat_aux,thr_stataux , ADN_none ) ;
01745 
01746       
01747 
01748       } else {
01749           EDIT_dset_items( new_dset , ADN_func_type,FUNC_THR_TYPE , ADN_none ) ;
01750       }
01751    }
01752 
01753    ivout++ ;
01754 
01755  }  
01756 
01757 
01758    
01759 
01760    tross_Make_History( "3dmerge" , argc , argv , new_dset ) ;
01761    THD_load_statistics( new_dset ) ;
01762    THD_write_3dim_dataset( NULL,NULL , new_dset , True ) ;
01763    if( ! MRG_be_quiet )
01764      fprintf(stderr,"-- Wrote merged dataset: %s\n" , DSET_BRIKNAME(new_dset) ) ;
01765    exit(0) ;
01766 }