Exemple #1
0
THD_3dim_dataset *Seg_load_dset_eng( char *set_name, char *view ) 
{
   static char FuncName[]={"Seg_load_dset_eng"};
   THD_3dim_dataset *dset=NULL, *sdset=NULL;
   int i=0;
   byte make_cp=0;
   int verb=0;
   char sprefix[THD_MAX_PREFIX+10], *stmp=NULL;
   
   SUMA_ENTRY;
   
   dset = THD_open_dataset( set_name );
   if( !ISVALID_DSET(dset) ){
     fprintf(stderr,"**ERROR: can't open dataset %s\n",set_name) ;
     SUMA_RETURN(NULL);
   }
   
   DSET_mallocize(dset)   ; DSET_load(dset);
   
   for (i=0; i<DSET_NVALS(dset); ++i) {
      if (DSET_BRICK_TYPE(dset,i) != MRI_short) {
         if (verb) INFO_message("Sub-brick %d in %s not of type short.\n"
                       "Creating new short copy of dset ", 
                       i, DSET_PREFIX(dset));
         make_cp=1; break;
      }
   }
   
   if (make_cp) {
      if (!SUMA_ShortizeDset(&dset, -1.0)) {
         SUMA_S_Err("**ERROR: Failed to shortize");
         SUMA_RETURN(NULL);
      }
   }
   
   if (DSET_IS_MASTERED(dset)) {
      if (verb) INFO_message("Dset is mastered, making copy...");
      stmp = SUMA_ModifyName(set_name, "append", ".cp", NULL);
      sdset = dset;
      dset = EDIT_full_copy(sdset, stmp);
      free(stmp); DSET_delete(sdset); sdset = NULL;  
   }
      
   
   if (view) {
      if (view) {
               if (!strstr(view,"orig")) 
            EDIT_dset_items(dset,ADN_view_type, VIEW_ORIGINAL_TYPE, ADN_none); 
         else  if (!strstr(view,"acpc")) 
            EDIT_dset_items(dset,ADN_view_type, VIEW_ACPCALIGNED_TYPE, ADN_none);
         else  if (!strstr(view,"tlrc")) 
            EDIT_dset_items(dset ,ADN_view_type, VIEW_TALAIRACH_TYPE, ADN_none);
         else SUMA_S_Errv("View of %s is rubbish", view);
      }
   }
   
   SUMA_RETURN(dset);
}
Exemple #2
0
void output_results (THD_3dim_dataset * new_dset)
{
  int ierror;     /* flag for errors in editing dataset */


  /*----- Make sure that output is a bucket dataset -----*/
  ierror = EDIT_dset_items( new_dset ,
			    ADN_func_type , FUNC_BUCK_TYPE,
			    ADN_none ) ;
  if (ierror > 0)  
    FDR_error ("Errors in attempting to create output dataset.");


  /*----- Output the FDR dataset -----*/
  if( !FDR_quiet ) fprintf(stderr,"Computing sub-brick statistics\n") ;
  THD_load_statistics( new_dset ) ;

  THD_write_3dim_dataset( NULL,NULL , new_dset , True ) ;
  if( !FDR_quiet ) fprintf(stderr,"Wrote output to %s\n", DSET_BRIKNAME(new_dset) );
  

  /*----- Deallocate memory for output dataset -----*/   
  THD_delete_3dim_dataset( new_dset , False ) ; new_dset = NULL ;
  
}
THD_3dim_dataset * GRINCOR_extract_dataset( MRI_shindss *shd, int ids, char *pref )
{
   MRI_vectim *mv ;
   THD_3dim_dataset *dset ;
   char prefix[THD_MAX_NAME] ;
   int iv , nvals=shd->nvals[ids] ;
   static int nds=0 ;

ENTRY("GRINCOR_extract_dataset") ;

STATUS("extract vectim") ;
   mv = GRINCOR_extract_vectim( shd , ids ) ;

STATUS("create empty copy of template") ;
   dset = EDIT_empty_copy( shd->tdset ) ;

STATUS("edit prefix") ;
   prefix[0] = '\0' ;
   if( pref != NULL && *pref != '\0' ){ strcpy(prefix,pref) ; strcat(prefix,"_") ; }
   if( shd->dslab != NULL && shd->dslab[ids] != NULL ){
     strcat(prefix,shd->dslab[ids]) ;
   } else {
     nds++ ;
     sprintf(prefix+strlen(prefix),"%03d",nds) ;
   }

STATUS("edit empty copy header") ;
   EDIT_dset_items( dset ,
                      ADN_prefix    , prefix          ,
                      ADN_nvals     , nvals           ,
                      ADN_ntt       , nvals           ,
                      ADN_ttdel     , 1.0             ,
                      ADN_tunits    , UNITS_SEC_TYPE  ,
                      ADN_brick_fac , NULL            ,
                      ADN_type      , HEAD_FUNC_TYPE  ,
                      ADN_func_type , FUNC_FIM_TYPE   ,
                    ADN_none ) ;

STATUS("create empty float bricks") ;
   for( iv=0 ; iv < nvals ; iv++ )
     EDIT_substitute_brick( dset , iv , MRI_float , NULL ) ;

STATUS("copy index vector") ;
   if( shd->ivec != NULL ){
     memcpy( mv->ivec , shd->ivec , sizeof(int)*shd->nvec ) ;
   } else {
     for( iv=0 ; iv < shd->nvec ; iv++ ) mv->ivec[iv] = iv ;
   }

STATUS("convert vectim to dset") ;
   THD_vectim_to_dset( mv , dset ) ;

STATUS("destroy vectim") ;
   VECTIM_destroy( mv ) ;

   RETURN(dset) ;
}
Exemple #4
0
int GenFeatureDist(SEG_OPTS *Opt) 
{
   
   ENTRY("GenFeatureDist");
   
   
   /* get the probability maps */
   if (!Opt->pset && Opt->DO_p) {
      if (!(Opt->pset = p_C_GIV_A(Opt))) {
         ERROR_message("Failed miserably");
         RETURN(0);
      }
   }
      
   /* Get the classes */
   if (!Opt->cset && Opt->crefix && Opt->DO_c) {
      if (!(SUMA_assign_classes_eng(Opt->pset, 
                           Opt->clss->str, Opt->clss->num, Opt->keys, 
                           Opt->cmask, &Opt->cset))) {
         ERROR_message("Failed aimlessly");
         RETURN(0);
      }
      EDIT_dset_items(Opt->cset, ADN_prefix, Opt->crefix, ADN_none);
      if( !THD_ok_overwrite() && THD_is_file( DSET_HEADNAME(Opt->cset) ) ){
      ERROR_exit("Output file %s already exists -- cannot continue!\n",
                  DSET_HEADNAME(Opt->cset) ) ;
      }
   }  
   
   /* group classes ? */
   if (Opt->group_classes) {
      THD_3dim_dataset *gcset=NULL;
      THD_3dim_dataset *gpset=NULL;
      if (!SUMA_Regroup_classes (Opt, 
                     Opt->clss->str, Opt->clss->num, Opt->keys,
                     Opt->group_classes->str,
                     Opt->group_classes->num,
                     Opt->group_keys, Opt->cmask,
                     Opt->pset, 
                     Opt->cset,
                     &gpset, 
                     &gcset) ) {
         ERROR_message("Failed to regroup");
         RETURN(0);
      }
      DSET_write(gpset);
      DSET_write(gcset);
   }
          
   RETURN(1);
}
/* convert by hand, since no scaling will be done
 * (byte seems inappropriate and float does not need it)  */
int write_result(param_t * params, THD_3dim_dataset * oset,
                 int argc, char * argv[])
{
   short * sptr;
   int     nvox = DSET_NVOX(oset), ind;

   ENTRY("write_results");

   EDIT_dset_items(oset, ADN_prefix, params->prefix, ADN_none);

   if( params->verb )
      INFO_message("writing result %s...\n", DSET_PREFIX(oset));

   switch( params->datum ) {
      default: ERROR_exit("invalid datum for result: %d", params->datum);
      case MRI_short: break;     /* nothing to do */
      case MRI_float: {
         float * data = (float *)malloc(nvox*sizeof(float));
         sptr = DBLK_ARRAY(oset->dblk, 0);
         if( ! data ) ERROR_exit("failed to alloc %d output floats\n", nvox);
         for( ind = 0; ind < nvox; ind++ ) data[ind] = (float)sptr[ind];
         EDIT_substitute_brick(oset, 0, params->datum, data);
      }
      break;
      case MRI_byte: {
         byte * data = (byte *)malloc(nvox*sizeof(byte));
         int errs = 0;
         sptr = DBLK_ARRAY(oset->dblk, 0);
         if( ! data ) ERROR_exit("failed to alloc %d output bytes\n", nvox);
         for( ind = 0; ind < nvox; ind++ ) {
            if( sptr[ind] > 255 ) {     /* watch for overflow */
               data[ind] = (byte)255;
               errs++;
            } else data[ind] = (byte)sptr[ind];
         }
         EDIT_substitute_brick(oset, 0, params->datum, data);
         if(errs) WARNING_message("convert to byte: %d truncated voxels",errs);
      }
      break;
   }

   tross_Make_History( "3dmask_tool", argc, argv, oset );

   DSET_write(oset);
   WROTE_DSET(oset);

   RETURN(0);
}
Exemple #6
0
void check_one_output_file 
(
  THD_3dim_dataset * dset_time,     /* input 3d+time data set */
  char * filename                   /* name of output file */
)

{
  char message[THD_MAX_NAME];      /* error message */
  THD_3dim_dataset * new_dset=NULL;   /* output afni data set pointer */
  int ierror;                         /* number of errors in editing data */

ENTRY("check_one_output_file") ;
  
  /*----- make an empty copy of input dataset -----*/
  new_dset = EDIT_empty_copy( dset_time ) ;
  
  
  ierror = EDIT_dset_items( new_dset ,
			    ADN_prefix , filename ,
			    ADN_label1 , filename ,
			    ADN_self_name , filename ,
			    ADN_type , ISHEAD(dset_time) ? HEAD_FUNC_TYPE : 
                               			           GEN_FUNC_TYPE ,
			    ADN_none ) ;
  
  if( ierror > 0 )
    {
      sprintf (message,
	       "*** %d errors in attempting to create output dataset!\n", 
	       ierror);
      FDR_error (message);
    }
  
  if( THD_is_file(new_dset->dblk->diskptr->header_name) )
    {
      sprintf (message,
	       "Output dataset file %s already exists "
	       " -- cannot continue! ",
	       new_dset->dblk->diskptr->header_name);
      FDR_error (message);
    }
  
  /*----- deallocate memory -----*/   
  THD_delete_3dim_dataset( new_dset , False ) ; new_dset = NULL ;
 
  EXRETURN ; 
}
Exemple #7
0
int main( int argc , char * argv[] )
{
   int kk , nvox , ii ;
   THD_3dim_dataset * oset ;
   float * far ;

   /*-- read command line arguments --*/

   if( argc < 2 || strncmp(argv[1],"-help",5) == 0 ) UC_syntax(NULL) ;

   (void) my_getenv("junk") ;

   UC_read_opts( argc , argv ) ;
   set_unusuality_tail( UC_ptail ) ;

   oset = EDIT_empty_copy( UC_dset ) ;
   EDIT_dset_items( oset ,
                       ADN_prefix      , UC_prefix ,
                       ADN_ntt         , 0 ,
                       ADN_nvals       , 1 ,
                       ADN_datum_all   , MRI_float ,
                       ADN_malloc_type , DATABLOCK_MEM_MALLOC ,
                    ADN_none ) ;

   nvox = DSET_NVOX(oset) ;
   far = (float *) malloc( sizeof(float) * nvox ) ;
   for( kk=0 ; kk < nvox ; kk++ ) far[kk] = 0.0 ;
   EDIT_substitute_brick( oset , 0 , MRI_float , far ) ;

   if( !UC_be_quiet ){ printf("--- computing u") ; fflush(stdout) ; }

   for( kk=0 ; kk < UC_nvec ; kk++ ){
      ii = (UC_iv == NULL) ? kk : UC_iv[kk] ;
      far[ii] = UC_unusuality( UC_vdim, UC_vec[kk] , UC_nvec, UC_vec ) ;
      if( !UC_be_quiet && kk%1000==999 ){ printf(".");fflush(stdout); }
   }
   if( !UC_be_quiet ) printf("\n--- writing output\n") ;

   DSET_write(oset) ;
   exit(0) ;
}
THD_3dim_dataset * GRINCOR_extract_dataset( MRI_shindss *shd, int ids, char *pref )
{
   MRI_vectim *mv ;
   THD_3dim_dataset *dset ;
   char prefix[THD_MAX_NAME] ;
   int iv , nvals=shd->nvals[ids] ;

   mv = GRINCOR_extract_vectim( shd , ids ) ;

   dset = EDIT_empty_copy( shd->tdset ) ;

   prefix[0] = '\0' ;
   if( pref != NULL && *pref != '\0' ){ strcpy(prefix,pref) ; strcat(prefix,"_") ; }
   strcat(prefix,shd->dslab[ids]) ;

   EDIT_dset_items( dset ,
                      ADN_prefix    , prefix          ,
                      ADN_nvals     , nvals           ,
                      ADN_ntt       , nvals           ,
                      ADN_ttdel     , 1.0             ,
                      ADN_tunits    , UNITS_SEC_TYPE  ,
                      ADN_brick_fac , NULL            ,
                      ADN_type      , HEAD_FUNC_TYPE  ,
                      ADN_func_type , FUNC_FIM_TYPE   ,
                    ADN_none ) ;

   for( iv=0 ; iv < nvals ; iv++ )
     EDIT_substitute_brick( dset , iv , MRI_float , NULL ) ;

   if( shd->ivec != NULL ){
     memcpy( mv->ivec , shd->ivec , sizeof(int)*shd->nvec ) ;
   } else {
     for( iv=0 ; iv < shd->nvec ; iv++ ) mv->ivec[iv] = iv ;
   }

   THD_vectim_to_dset( mv , dset ) ;
   VECTIM_destroy( mv ) ;

   return dset ;
}
Exemple #9
0
int WB_netw_corr(int Do_r, 
                 int Do_Z,
                 int HAVE_ROIS, 
                 char *prefix, 
                 int NIFTI_OUT,
                 int *NROI_REF,
                 int *Dim,
                 double ***ROI_AVE_TS,
                 int **ROI_LABELS_REF,
                 THD_3dim_dataset *insetTIME,
                 byte *mskd2,
                 int Nmask,
                 int argc,
                 char *argv[])
{
   int i,j,k;
   float **AVE_TS_fl=NULL;    // not great, but another format of TS
   char OUT_indiv0[300];
   char OUT_indiv[300];
   char OUT_indivZ[300];
   MRI_IMAGE *mri=NULL;
   THD_3dim_dataset *OUT_CORR_MAP=NULL;
   THD_3dim_dataset *OUT_Z_MAP=NULL;
   float *zscores=NULL;
   int Nvox;


   Nvox = Dim[0]*Dim[1]*Dim[2];

   // make average time series per voxel
   AVE_TS_fl = calloc( 1,sizeof(AVE_TS_fl));  
   for(i=0 ; i<1 ; i++) 
      AVE_TS_fl[i] = calloc(Dim[3],sizeof(float)); 
   
   if( (AVE_TS_fl == NULL) ) {
      fprintf(stderr, "\n\n MemAlloc failure (time series out).\n\n");
      exit(123);
   }

   fprintf(stderr,"\nHAVE_ROIS=%d",HAVE_ROIS);
   for( k=0 ; k<HAVE_ROIS ; k++) { // each netw gets own file
      sprintf(OUT_indiv0,"%s_%03d_INDIV", prefix, k);
      mkdir(OUT_indiv0, 0777);
      for( i=0 ; i<NROI_REF[k] ; i++ ) {
         fprintf(stderr,"\nNROI_REF[%d]= %d",k,NROI_REF[k]);
         for( j=0 ; j<Dim[3] ; j++)
            AVE_TS_fl[0][j] = (float) ROI_AVE_TS[k][i][j];
         if( NIFTI_OUT )
            sprintf(OUT_indiv,"%s/WB_CORR_ROI_%03d.nii.gz",
                    OUT_indiv0,ROI_LABELS_REF[k][i+1]);
         else
            sprintf(OUT_indiv,"%s/WB_CORR_ROI_%03d",
                    OUT_indiv0,ROI_LABELS_REF[k][i+1]);
         mri = mri_float_arrays_to_image(AVE_TS_fl,Dim[3],1);
         OUT_CORR_MAP = THD_Tcorr1D(insetTIME, mskd2, Nmask,
                                    mri,
                                    "pearson", OUT_indiv);
         if(Do_r){
            THD_load_statistics(OUT_CORR_MAP);
            tross_Copy_History( insetTIME , OUT_CORR_MAP ) ;
            tross_Make_History( "3dNetcorr", argc, argv, OUT_CORR_MAP );
            if( !THD_ok_overwrite() && 
                THD_is_ondisk(DSET_HEADNAME(OUT_CORR_MAP)) )
               ERROR_exit("Can't overwrite existing dataset '%s'",
                          DSET_HEADNAME(OUT_CORR_MAP));
            THD_write_3dim_dataset(NULL, NULL, OUT_CORR_MAP, True);
            INFO_message("Wrote dataset: %s\n",DSET_BRIKNAME(OUT_CORR_MAP));

         }
         if(Do_Z){
          if( NIFTI_OUT )
             sprintf(OUT_indivZ,"%s/WB_Z_ROI_%03d.nii.gz",
                     OUT_indiv0,ROI_LABELS_REF[k][i+1]);
          else
             sprintf(OUT_indivZ,"%s/WB_Z_ROI_%03d",
                     OUT_indiv0,ROI_LABELS_REF[k][i+1]);

            OUT_Z_MAP = EDIT_empty_copy(OUT_CORR_MAP);
            EDIT_dset_items( OUT_Z_MAP,
                             ADN_nvals, 1,
                             ADN_datum_all , MRI_float , 
                             ADN_prefix    , OUT_indivZ,
                             ADN_none ) ;
            if( !THD_ok_overwrite() && 
                THD_is_ondisk(DSET_HEADNAME(OUT_Z_MAP)) )
               ERROR_exit("Can't overwrite existing dataset '%s'",
                          DSET_HEADNAME(OUT_Z_MAP));

            zscores = (float *)calloc(Nvox,sizeof(float)); 
            if( (zscores == NULL) ) {
               fprintf(stderr, "\n\n MemAlloc failure (zscores).\n\n");
               exit(123);
            }

            for( j=0 ; j<Nvox ; j++ )
              if( mskd2[j] ) // control for r ==1
                 BOBatanhf( THD_get_voxel(OUT_CORR_MAP, j, 0) );
                 /*
                 if( THD_get_voxel(OUT_CORR_MAP, j, 0) > MAX_R )
                   zscores[j] = (float) atanh(MAX_R);
                 else if ( THD_get_voxel(OUT_CORR_MAP, j, 0) < -MAX_R )
                   zscores[j] =  (float) atanh(-MAX_R);
                 else
                 zscores[j] = (float) atanh(THD_get_voxel(OUT_CORR_MAP, j, 0));*/
            
            EDIT_substitute_brick(OUT_Z_MAP, 0, MRI_float, zscores); 
            zscores=NULL;

            THD_load_statistics(OUT_Z_MAP);
            tross_Copy_History(insetTIME, OUT_Z_MAP);
            tross_Make_History("3dNetcorr", argc, argv, OUT_Z_MAP);
            THD_write_3dim_dataset(NULL, NULL, OUT_Z_MAP, True);
            INFO_message("Wrote dataset: %s\n",DSET_BRIKNAME(OUT_Z_MAP));

            DSET_delete(OUT_Z_MAP);
            free(OUT_Z_MAP);
            OUT_Z_MAP=NULL;
         }

         DSET_delete(OUT_CORR_MAP);
         free(OUT_CORR_MAP);
         OUT_CORR_MAP=NULL;
      }
   }
   
   free(zscores);
   mri_free(mri);
   for( i=0 ; i<1 ; i++) 
      free(AVE_TS_fl[i]);
   free(AVE_TS_fl);

   RETURN(1);
}
char * SUMA_BrainVoyager_Read_vmr(char *fnameorig, THD_3dim_dataset *dset, int LoadData, 
                                  byte Qxforce, byte bsforce, int viewforce, char *outname)
{
   static char FuncName[]={"SUMA_BrainVoyager_Read_vmr"};
   int  i = 0, nf, iop, dchunk, End, bs, doff, ex,
         data_type=SUMA_notypeset, view, endian, dblock;
   THD_ivec3 iv3;
   unsigned long len;
   short qxver;
   short nvox[3]; /* values are unsigned, so check for sign for bs... */
   THD_mat33 m33;
   THD_ivec3 orixyz , nxyz ;
   THD_fvec3 dxyz , orgxyz ;
   float ep[3], sp[3];
   char sview[10], *fname = NULL, *scom=NULL, form[10], swp[10], orstr[10], xfov[100], yfov[100], zfov[100], *prefix = NULL, *dsetheadname = NULL;
   FILE *fid = NULL;
   SUMA_Boolean LocalHead = NOPE;
   
   SUMA_ENTRY;
   
   if (!dset || !fnameorig) {
      SUMA_SL_Err("NULL fname || NULL dset!");
      SUMA_RETURN(NOPE);
   }
   
   if (!SUMA_isExtension(fnameorig, ".vmr")) {
      SUMA_SL_Err("vmr dset is expected to have .vmr for an extension");
      SUMA_RETURN(NOPE);
   }
   
   if (!SUMA_filexists(fnameorig)) {
      SUMA_SL_Err("file does not exist");
      SUMA_RETURN(NOPE);
   }
   
   /* make fname be the new name without the extension*/
   if (!outname) {
      fname = SUMA_Extension(fnameorig,".vmr", YUP);
   } else {
      fname = SUMA_Extension(outname, ".vmr", YUP);
   }
   prefix = SUMA_AfniPrefix(fname, NULL, NULL, NULL);
   if( !THD_filename_ok(prefix) ) {
      SUMA_SL_Err("Bad prefix");
      goto CLEAN_EXIT;
   }
   
   /* someday, guess format on your own...*/
   qxver = 0;
   if (Qxforce) {
      SUMA_LH("Forcing qxver");
      qxver = 1;  /* set to 1 if qx format */
   } 
   
   /* view ? */
   SUMA_LHv("Viewforce = %d; [%d %d]\n", viewforce, VIEW_ORIGINAL_TYPE, VIEW_TALAIRACH_TYPE);
   if (viewforce >=  VIEW_ORIGINAL_TYPE && viewforce <= VIEW_TALAIRACH_TYPE) {
      view = viewforce;
   } else {
      view = VIEW_ORIGINAL_TYPE;
      if (SUMA_iswordin_ci(fnameorig, "_tal") == 1) { view = VIEW_TALAIRACH_TYPE; }
      else if (SUMA_iswordin_ci(fnameorig, "_acpc") == 1) { view = VIEW_ACPCALIGNED_TYPE; } 
      else { view = VIEW_ORIGINAL_TYPE;  } 
   }
   switch (view) {
      case VIEW_ORIGINAL_TYPE:
         sprintf(sview,"+orig"); break;
      case VIEW_ACPCALIGNED_TYPE:
         sprintf(sview,"+acpc"); break;
      case VIEW_TALAIRACH_TYPE: 
         sprintf(sview,"+tlrc"); break;
      default:
         SUMA_SL_Err("Bad view");
         goto CLEAN_EXIT; 
   }
   
   if (LocalHead) fprintf(SUMA_STDERR,"%s: View %s, %d\n", FuncName, sview, view);    
   
   dsetheadname = SUMA_append_replace_string(prefix,".HEAD", sview, 0);
   if (SUMA_filexists(dsetheadname)) {
      SUMA_S_Errv("Bad prefix, output dset %s exists\n", dsetheadname);
      goto CLEAN_EXIT;
   }
   SUMA_free(dsetheadname); dsetheadname = NULL;
   
   fid = fopen(fnameorig,"r"); 
   if (!fid) {
      SUMA_SL_Err("Could not open file for reading");
      goto CLEAN_EXIT;      
   }
   
   if (qxver) { 
      SUMA_LH("Reading dimensions, 2+ 1st 6 bytes and deciding on swap");
      doff = 4*sizeof(short);/* data offset 2 + 6 bytes */
   } else {
      SUMA_LH("Reading dimensions, 1st 6 bytes and deciding on swap");
      doff = 3*sizeof(short);/* data offset */
   }
   SUMA_WHAT_ENDIAN(endian);
   bs = 0;
   swp[0] = '\0';
   data_type = SUMA_byte; /* voxel data is bytes */
   dchunk = sizeof(byte); /* voxel data is bytes */
   sprintf(form,"3Db");
   if (qxver) { SUMA_READ_NUM(&(qxver), fid, ex, sizeof(short)); if (LocalHead) fprintf(SUMA_STDERR,"%s: QXver = %d\n", FuncName, qxver);}/* is this a QX format?*/
   SUMA_READ_NUM(&(nvox[2]), fid, ex, sizeof(short)); /* Z first */
   SUMA_READ_NUM(&(nvox[1]), fid, ex, sizeof(short));
   SUMA_READ_NUM(&(nvox[0]), fid, ex, sizeof(short));
   
   if ((nvox[0] < 0 || nvox[1] < 0 || nvox[2] < 0 )) {
      SUMA_LH("Byte swapping needed");
      bs = 1;
   }
   if (bsforce) {
      SUMA_LH("Byte swapping forced");
      bs = 1;
   }
   
   
   if (bs) {
      if (qxver) SUMA_swap_2(&(qxver));
      SUMA_swap_2(&(nvox[0]));
      SUMA_swap_2(&(nvox[1]));
      SUMA_swap_2(&(nvox[2]));
      sprintf(swp,"-2swap");
      SUMA_OTHER_ENDIAN(endian);
   }
   
   /* 1 1 1???? */
   if (nvox[0] == nvox[1]  && nvox[1] == nvox[2] && nvox[2] == 1) {
      if (LocalHead) { fprintf(SUMA_STDERR,"Warning %s: Voxel nums all 1. Trying from file size\n", FuncName); }
      len = THD_filesize( fnameorig ) ;
      len -= doff;
      len /= dchunk;
      nvox[0] = (int)pow((double)len, 1.0/3.0); 
      if (nvox[0] * nvox[0] * nvox[0] != len) {
         fprintf(SUMA_STDERR,"Error %s: Bad voxel numbers and could not infer number from filesize.\n"
                             "Size of file: %lld, data offset: %d, datum size: %d, data number: %ld\n"
                             "Inferred nvox:%d\n",
                             FuncName,
                             THD_filesize( fnameorig ), doff, dchunk, len, 
                             nvox[0]);
         goto CLEAN_EXIT;
      }
      nvox[2] = nvox[1] = nvox[0];
      if (LocalHead) { fprintf(SUMA_STDERR,"Warning %s: Using filesize inferred number of voxels: %d %d %d\n", 
                              FuncName, nvox[0], nvox[1], nvox[2]); }
   }
   
   if (LocalHead) fprintf(SUMA_STDERR,"Number of voxels: %d %d %d. qxver %d\n", nvox[0], nvox[1], nvox[2], qxver);
   

   /* check against filesize */
   
   len = THD_filesize( fnameorig ) ;
   dblock = nvox[0]*nvox[1]*nvox[2]*dchunk;
   if (len != (dblock + doff)) {
      if (!qxver) {
         fprintf(SUMA_STDERR, "Mismatch between file size    %ld\n"
                              "and expected size             %d = (%d*%d*%d*%d+%d) \n",
                              len, (dblock + doff), nvox[0], nvox[1], nvox[2], dchunk, doff);
         goto CLEAN_EXIT; 
      }else if (len < dblock + doff) {
         fprintf(SUMA_STDERR, "Mismatch between file size    %ld\n"
                              "and minimum expected size     %d = (%d*%d*%d*%d+%d) \n",
                              len, (dblock + doff), nvox[0], nvox[1], nvox[2], dchunk, doff);
         goto CLEAN_EXIT; 
      }else {
         SUMA_LH("Proceeding");
      }
   }
   if (LocalHead) fprintf(SUMA_STDERR,"File size passes test\n");

   /* orientation */
   
   orixyz.ijk[0] = ORI_A2P_TYPE;
   orixyz.ijk[1] = ORI_S2I_TYPE;
   orixyz.ijk[2] = ORI_R2L_TYPE;       
   
   /* load number of voxels */
   LOAD_IVEC3( nxyz   , nvox[0]    , nvox[1]    , nvox[2] ) ;
  
   /* form the command */
   SUMA_LH("Forming command");
   
   {  
      float delta[3]={1.0, 1.0, 1.0};
      float origin[3]={0.0, 0.0, 0.0}; 
      /* set origin of 0th voxel*/
      origin[0] = (float)((nvox[0]*delta[0]))/2.0;    /* ZSS: Changed from 0 0 0 Nov 1 07 */
      origin[1] = (float)((nvox[1]*delta[1]))/2.0;
      origin[2] = (float)((nvox[2]*delta[2]))/2.0;
       
      /* dimensions, same for vmr*/
      LOAD_FVEC3( dxyz , delta[0], delta[1], delta[2]   ) ;
      SUMA_sizeto3d_2_deltaHEAD(orixyz, &dxyz);
      /* origin */
      LOAD_FVEC3( orgxyz , origin[0], origin[1], origin[2]   ) ;
      SUMA_originto3d_2_originHEAD(orixyz, &orgxyz);
      
   }
    
   /* start point (edge of origin voxel) and end point (opposite to start ) */
   sp[0] = orgxyz.xyz[0] + SUMA_ABS(dxyz.xyz[0]) / 2.0;
   sp[1] = orgxyz.xyz[1] + SUMA_ABS(dxyz.xyz[1]) / 2.0;
   sp[2] = orgxyz.xyz[2] + SUMA_ABS(dxyz.xyz[2]) / 2.0;
   ep[0] = orgxyz.xyz[0] + (nxyz.ijk[0] - 0.5) * SUMA_ABS(dxyz.xyz[0]);
   ep[1] = orgxyz.xyz[1] + (nxyz.ijk[1] - 0.5) * SUMA_ABS(dxyz.xyz[1]);
   ep[2] = orgxyz.xyz[2] + (nxyz.ijk[2] - 0.5) * SUMA_ABS(dxyz.xyz[2]);
   SUMA_orcode_to_orstring (orixyz.ijk[0], orixyz.ijk[1], orixyz.ijk[2], orstr);
   sprintf(xfov," -xFOV %.2f%c-%.2f%c", sp[0], orstr[0], ep[0], orstr[3]);
   sprintf(yfov," -yFOV %.2f%c-%.2f%c", sp[1], orstr[1], ep[1], orstr[4]);
   sprintf(zfov," -zFOV %.2f%c-%.2f%c", sp[2], orstr[2], ep[2], orstr[5]);
  
   scom = (char *)SUMA_calloc((strlen(fnameorig)+500), sizeof(char));
   sprintf(scom,"to3d %s %s %s %s -prefix %s %s:%d:0:%d:%d:%d:%s ", 
            swp, xfov, yfov, zfov, prefix, form, doff, 
            nvox[0], nvox[1], nvox[0], fnameorig);
   
   SUMA_LH("HERE");
   
   if (dset) { /* form the dset header */
         int nvals_read = 0;
         SUMA_LH("Filling header");
         EDIT_dset_items( dset ,
                            ADN_prefix      , prefix ,
                            ADN_datum_all   , data_type ,
                            ADN_nxyz        , nxyz ,
                            ADN_xyzdel      , dxyz ,
                            ADN_xyzorg      , orgxyz ,
                            ADN_xyzorient   , orixyz ,
                            ADN_malloc_type , DATABLOCK_MEM_MALLOC ,
                            ADN_view_type   , view ,
                            ADN_type        , HEAD_ANAT_TYPE ,
                            ADN_func_type   , ANAT_BUCK_TYPE ,
                          ADN_none ) ;

         if (LoadData) {
            void *vec=NULL;
            SUMA_LH("Loading data");
            if (!(vec = SUMA_BinarySuck(fnameorig, data_type, endian, 3*sizeof(short), -1, &nvals_read))) {
               SUMA_SL_Err("Failed to read data file"); goto CLEAN_EXIT;
            }
            if (qxver) {
               if (nvals_read < nvox[0]*nvox[1]*nvox[2]) {
                  SUMA_SL_Warn("Failed to read expected number of voxels\n proceeding...");
               }
            } else {
               if (nvals_read != nvox[0]*nvox[1]*nvox[2]) {
                  SUMA_SL_Warn("Failed to read the appropriate number of voxels\n proceeding...");
               }
            }  
            EDIT_substitute_brick( dset , 0 , data_type , vec) ;      
            if (LocalHead) fprintf(SUMA_STDERR,"%s: Read %d values from file.\n", FuncName, nvals_read);
            /* DSET_write(dset) ; */
         }
   }
   

   
   CLEAN_EXIT:
   if (prefix) SUMA_free(prefix); prefix = NULL;
   if (fname) SUMA_free(fname); fname = NULL;
   if (fid) fclose(fid); fid = NULL;
   SUMA_RETURN(scom);
}
THD_3dim_dataset * THD_open_tcat( char *dlist )
{
   THD_3dim_dataset *dset_out , **dset_in ;
   int ndset_in , dd , nerr , new_nvals, sb=0 ;
   NI_str_array *sar ;
   double angle=0.0;
   char *dp, *dlocal = dlist;   /* local dlist, in case it is altered */
   
ENTRY("THD_open_tcat") ;

   if( dlocal == NULL || *dlocal == '\0' ) RETURN(NULL) ;

   /* allow file list to be read from a file   23 Jul 2012 [rickr] */
   if( ! strncmp(dlocal, "filelist:", 9) ) {
      dlocal = AFNI_suck_file(dlocal+9) ;
      if ( ! dlocal ) {
         ERROR_message("THD_open_tcat: failed to open '%s' as filelist",
                       dlocal+9);
         RETURN(NULL) ;
      }
      /* make it look more like expected */
      for( dd=0, dp=dlocal; dd < strlen(dlocal); dd++, dp++ )
         if( *dp == '\n' || *dp  == '\r' ) *dp = ' ';
   }

   if( strchr(dlocal,' ') == NULL ){
     dset_out = THD_open_dataset(dlocal) ; RETURN(dset_out) ;
   }

   sar = NI_decode_string_list( dlocal , "~" ) ;
   if( sar == NULL ) RETURN(NULL) ;

   ndset_in = sar->num ;
   dset_in  = (THD_3dim_dataset **)malloc(sizeof(THD_3dim_dataset *)*sar->num) ;
   for( nerr=dd=0 ; dd < ndset_in ; dd++ ){
     dset_in[dd] = THD_open_dataset( sar->str[dd] ) ;
     if( dset_in[dd] == NULL ){
       fprintf(stderr,"** THD_open_tcat: can't open dataset %s\n",sar->str[dd]) ;
       nerr++ ;
     }
   }
   if( nerr > 0 ){
     for( dd=0 ; dd < ndset_in ; dd++ )
       if( dset_in[dd] != NULL ) DSET_delete(dset_in[dd]) ;
     free((void *)dset_in) ;
     NI_delete_str_array(sar) ;
     RETURN(NULL) ;
   }
   if( ndset_in == 1 ){
     dset_out = dset_in[0] ;
     free((void *)dset_in) ;
     NI_delete_str_array(sar) ;
     RETURN(dset_out) ;
   }

   (void)THD_check_for_duplicates( sar->num , sar->str , 1 ) ;  /* 31 May 2007 */

   for( nerr=0,dd=1 ; dd < ndset_in ; dd++ ){
     if( DSET_NX(dset_in[0]) != DSET_NX(dset_in[dd]) ||
         DSET_NY(dset_in[0]) != DSET_NY(dset_in[dd]) ||
         DSET_NZ(dset_in[0]) != DSET_NZ(dset_in[dd])   ){
       ERROR_message(
               "THD_open_tcat: %s [%dx%dx%d] doesn't match %s [%dx%dx%d]\n",
               sar->str[0] ,DSET_NX(dset_in[0]) ,
                            DSET_NY(dset_in[0]) ,DSET_NZ(dset_in[0]) ,
               sar->str[dd],DSET_NX(dset_in[dd]),
                            DSET_NY(dset_in[dd]),DSET_NZ(dset_in[dd]) ) ;
       nerr++ ;
     } else {
       if( !EQUIV_DATAXES(dset_in[dd]->daxes,dset_in[0]->daxes) ){
         WARNING_message(
                  "THD_open_tcat: %s grid mismatch with %s\n",
                  sar->str[0] , sar->str[dd] ) ;  /* don't increment nerr! */
       }
       angle = dset_obliquity_angle_diff(dset_in[dd], dset_in[0], -1.0);
       if (angle > 0.0) {
         WARNING_message(
            "dataset %s has an obliquity difference of %f degress with %s\n",
            dset_in[dd] ,
            angle, dset_in[0] );
       }
     }
   }
   if( nerr > 0 ){
     for( dd=0 ; dd < ndset_in ; dd++ )
       if( dset_in[dd] != NULL ) DSET_delete(dset_in[dd]) ;
     free((void *)dset_in) ;
     NI_delete_str_array(sar) ;
     RETURN(NULL) ;
   }

   /*-- Check for type problems                    ZSS: Aug 27 2012 --*/
   for (nerr=0,dd=0; dd < ndset_in ; dd++) {
      for (sb=0; sb < DSET_NVALS(dset_in[dd]); ++sb) {
         if ( DSET_BRICK_TYPE(dset_in[0],0) != 
              DSET_BRICK_TYPE(dset_in[dd],sb) ) {
            ++nerr;    
         }
      }
   }
   if (nerr > 0) { /* don't die, just complain */
      WARNING_message(
      "Command-line catenated dataset has %d sub-bricks that differ \n"
      "  in data type from the first sub-brick of the first set.\n"
      "  Mme Irma sees potential for grief if you go down that path. \n"
      "  Use 3dinfo -datum on each input to understand why this is happening.\n"
      "  You can use 3dcalc's -datum option to rewrite the dataset with \n"
      "  all sub-bricks set to the same type then start over.\n\n",
            nerr);
      nerr=0;
   }
   
   /*-- OK, start making new dataset --*/

   new_nvals = 0 ;
   for( dd=0 ; dd < ndset_in ; dd++ )
     new_nvals += DSET_NVALS(dset_in[dd]) ;

   for( dd=0 ; dd < ndset_in ; dd++ )
      if( DSET_TIMESTEP(dset_in[dd]) > 0.0 ) break ;  /* 1st 3D+time */
   if( dd == ndset_in ) dd = 0 ;

   dset_out = EDIT_empty_copy( dset_in[dd] ) ;

   /* since this is basically an input dataset, set the storage_mode
    * to match                                   27 Jul 2010 [rickr] */
   if( DSET_ONDISK(dset_out) && IS_VALID_NON_AFNI_DSET(dset_in[dd]) )
      THD_set_storage_mode(dset_out, dset_in[dd]->dblk->diskptr->storage_mode);

   EDIT_dset_items( dset_out ,
                      ADN_prefix    , "tcat" ,
                      ADN_func_type , ISANAT(dset_in[dd]) ? ANAT_EPI_TYPE
                                                          : FUNC_FIM_TYPE ,
                      ADN_ntt       , new_nvals ,
                      ADN_nvals     , new_nvals ,
                    ADN_none ) ;
   DSET_mallocize( dset_out ) ;

   /* check if we have a valid time axis; if not, make one up */

   if( DSET_TIMESTEP(dset_out) <= 0.0f ){
      float TR=1.0f , torg=0.0f , tdur=0.0f ;
      int tunits=UNITS_SEC_TYPE ;
      EDIT_dset_items( dset_out ,
                          ADN_tunits , tunits ,
                          ADN_ttdel  , TR ,
                          ADN_ttorg  , torg ,
                          ADN_ttdur  , tdur ,
                       ADN_none ) ;
   }

   dset_out->tcat_list = strdup( dlocal ) ;
   dset_out->tcat_num  = ndset_in ;
   dset_out->tcat_len  = (int *)malloc(sizeof(int)*ndset_in) ;
   for( dd=0 ; dd < ndset_in ; dd++ ){
     dset_out->tcat_len[dd] = DSET_NVALS(dset_in[dd]) ;
     DSET_delete(dset_in[dd]) ;
   }
   free((void *)dset_in) ;
   NI_delete_str_array(sar) ;

#if 0
fprintf(stderr,"THD_open_tcat('%s'):",dset_out->tcat_list);
for(dd=0;dd<ndset_in;dd++)fprintf(stderr," %d",dset_out->tcat_len[dd]);
fprintf(stderr,"\n");
#endif

   RETURN(dset_out) ;
}
Exemple #12
0
char * POWER_main( PLUGIN_interface * plint )
{
   MCW_idcode * idc ;                          /* input dataset idcode */
   THD_3dim_dataset * old_dset , * new_dsetD3 , * new_dsetA3, * new_dsetavgD3 ; /* input and output datasets */
   char * new_prefix , * str , * namestr, * filename;                 /* strings from user */
   int   new_datum , ignore , nfft , ninp ,    /* control parameters */
         old_datum , nuse , ntaper , ktbot,
         image_type, scale,OutputFlag ,numT,flip;
  float avFac;

   byte   ** bptr  = NULL ;  /* one of these will be the array of */
   short  ** sptr  = NULL ;  /* pointers to input dataset sub-bricks */
   float  ** fptr  = NULL ;  /* (depending on input datum type) */



   float   * this  = NULL ;  /* array loaded from input dataset */


   float  ** foutD3  = NULL ;  /* will be array of output floats */
   float  ** foutA3  = NULL ;  /* will be array of output floats */
   float  ** foutavgD3  = NULL ;  /* will be array of output floats */

   float   * tarD3   = NULL ;  /* will be array of taper coefficients */
   float   * tarA3   = NULL ;  /* will be array of taper coefficients */
   float   * taravgD3   = NULL ;  /* will be array of taper coefficients */


   /*float   * flip;*/
   float   * numAv;
   float dfreq , pfact , phi , xr,xi , yr,yi ;
   float x0,x1 , y0,y1 , d0fac,d1fac ;
   int   nfreq , nvox , perc , new_units ;
   int   istr , ii,iip , ibot,itop , kk , icx ;       /* temp variables */

   new_prefix = (char *)calloc(100, sizeof(char));
   filename = (char *)calloc(100, sizeof(char));
   str = (char *)calloc(100, sizeof(char));
   namestr = (char *)calloc(100, sizeof(char));
   OutputFlag=0;
   /*--------------------------------------------------------------------*/
   /*----- Check inputs from AFNI to see if they are reasonable-ish -----*/

   /*--------- go to first input line ---------*/

   PLUTO_next_option(plint) ;

   idc      = PLUTO_get_idcode(plint) ;   /* get dataset item */
   old_dset = PLUTO_find_dset(idc) ;      /* get ptr to dataset */
   namestr  = DSET_PREFIX(old_dset) ;


   if( old_dset == NULL )
      return "*************************\n"
             "Cannot find Input Dataset\n"
             "*************************"  ;

   /*--------- go to second input line ---------*/

   PLUTO_next_option(plint) ;

  filename = PLUTO_get_string(plint) ;   /* get string item (the output prefix) */

  sprintf(new_prefix,"%s%s",filename,"_D3");

  if (strcmp(new_prefix,"_D3")==0){
     OutputFlag=1;
     sprintf(new_prefix,"%s%s",namestr,"_D3");
  }


   if (! PLUTO_prefix_ok(new_prefix) ){
     PLUTO_popup_transient(plint,new_prefix);
     return "*************************\n"
             "Output filename already exists\n"
             "*************************"  ;
     }


   PLUTO_popup_transient(plint,"Output file tags set automatically");


   str  = PLUTO_get_string(plint) ;              /* get string item (the datum type) */
   istr = PLUTO_string_index( str ,              /* find it in the list it came from */
                              NUM_TYPE_STRINGS ,
                              type_strings ) ;
   switch( istr ){
      default:
      case 0:
         new_datum = MRI_float ; break ;
	 break ;

      case 1: new_datum = MRI_byte  ; break ;  /* assign type of user's choice */
      case 2: new_datum = MRI_short ; break ;
      case 3: new_datum = DSET_BRICK_TYPE( old_dset , 0 ) ;  /* use old dataset type */
   }

  /*--------- go to next input lines ---------*/

   PLUTO_next_option(plint) ;                 /* skip to next line */
   ignore = PLUTO_get_number(plint) ;         /* get number item (ignore) */




   ninp = DSET_NUM_TIMES(old_dset) ;   /* number of values in input */
   nuse = ninp;              /* number of values to actually use */
   nfreq=nuse;
   nfft=nuse;


   str  = PLUTO_get_string(plint) ;              /* get string item (the datum type) */
   istr = PLUTO_string_index( str ,              /* find it in the list it came from */
                              NUM_TYPE_STRINGSX ,
                              type_stringsx ) ;
   switch( istr ){
      default:
      case 0: image_type = 0; break;
           }

  PLUTO_next_option(plint) ;                 /* skip to next line */
  scale = PLUTO_get_number(plint) ;         /* get number item (scale) */


   /*------------------------------------------------------*/
   /*---------- At this point, the inputs are OK ----------*/

   PLUTO_popup_meter( plint ) ;  /* popup a progress meter */

   /*--------- set up pointers to each sub-brick in the input dataset ---------*/

   DSET_load( old_dset ) ;  /* must be in memory before we get pointers to it */

   old_datum = DSET_BRICK_TYPE( old_dset , 0 ) ; /* get old dataset datum type */

   switch( old_datum ){  /* pointer type depends on input datum type */

      default:
         return "******************************\n"
                "Illegal datum in Input Dataset\n"
                "******************************"  ;

      /** create array of pointers into old dataset sub-bricks **/
      /** Note that we skip the first 'ignore' sub-bricks here **/

      /*--------- input is bytes ----------*/
      /* voxel #i at time #k is bptr[k][i] */
      /* for i=0..nvox-1 and k=0..nuse-1.  */

      case MRI_byte:
         bptr = (byte **) malloc( sizeof(byte *) * nuse ) ;
         if( bptr == NULL ) return "Malloc\nFailure!\n [bptr]" ;
         for( kk=0 ; kk < nuse ; kk++ )
            bptr[kk] = (byte *) DSET_ARRAY(old_dset,kk) ;
      break ;

      /*--------- input is shorts ---------*/
      /* voxel #i at time #k is sptr[k][i] */
      /* for i=0..nvox-1 and k=0..nuse-1.  */

      case MRI_short:
         sptr = (short **) malloc( sizeof(short *) * nuse ) ;
         if( sptr == NULL ) return "Malloc\nFailure!\n [sptr]" ;
         for( kk=0 ; kk < nuse ; kk++ )
            sptr[kk] = (short *) DSET_ARRAY(old_dset,kk) ;
      break ;

      /*--------- input is floats ---------*/
      /* voxel #i at time #k is fptr[k][i] */
      /* for i=0..nvox-1 and k=0..nuse-1.  */

      case MRI_float:
         fptr = (float **) malloc( sizeof(float *) * nuse ) ;
         if( fptr == NULL ) return "Malloc\nFailure!\n [fptr]" ;
         for( kk=0 ; kk < nuse ; kk++ )
            fptr[kk] = (float *) DSET_ARRAY(old_dset,kk) ;
      break ;

   } /* end of switch on input type */

   /*---- allocate space for 2 voxel timeseries and 1 FFT ----*/



   this = (float *)   malloc( sizeof(float) * nuse ) ;   /* input */
   tarD3 = (float *) malloc( sizeof(float) * MAX(nuse,nfreq) ) ;
   tarA3 = (float *) malloc( sizeof(float) * MAX(nuse,nfreq) ) ;
   taravgD3 = (float *) malloc( sizeof(float) * MAX(nuse,nfreq) ) ;
   /*flip = (float *)malloc( sizeof(float) * 1);*/
   numAv = (float *)malloc( sizeof(float) * 1);


  numT=nuse-ignore;

  if (OutputFlag==1)
  sprintf(new_prefix,"%s%s",namestr,"_D3");
  else
  sprintf(new_prefix,"%s%s",filename,"_D3");

  new_dsetD3 = EDIT_empty_copy( old_dset );

  { char * his = PLUTO_commandstring(plint) ;
  tross_Copy_History( old_dset , new_dsetD3 ) ;
  tross_Append_History( new_dsetD3 , his ) ; free(his) ;
  }

   	/*-- edit some of its internal parameters --*/

  ii = EDIT_dset_items(
       new_dsetD3 ,
         ADN_prefix      , new_prefix ,           /* filename prefix */
         ADN_malloc_type , DATABLOCK_MEM_MALLOC , /* store in memory */
         ADN_datum_all   , new_datum ,            /* atomic datum */
	 ADN_nvals	      , numT ,
	 ADN_ntt	,numT,
         ADN_none ) ;



  if (OutputFlag==1)
  sprintf(new_prefix,"%s%s",namestr,"_A3");
  else
  sprintf(new_prefix,"%s%s",filename,"_A3");

  numT=nuse-ignore;
  new_dsetA3 = EDIT_empty_copy( old_dset );

  { char * his = PLUTO_commandstring(plint) ;
  tross_Copy_History( old_dset , new_dsetA3 ) ;
  tross_Append_History( new_dsetA3 , his ) ; free(his) ;
  }

   	/*-- edit some of its internal parameters --*/

  ii = EDIT_dset_items(
       new_dsetA3 ,
         ADN_prefix      , new_prefix ,           /* filename prefix */
         ADN_malloc_type , DATABLOCK_MEM_MALLOC , /* store in memory */
         ADN_datum_all   , new_datum ,            /* atomic datum */
	 ADN_nvals	      , numT,
	 ADN_ntt	,numT,
         ADN_none ) ;



  if (OutputFlag==1)
  sprintf(new_prefix,"%s%s",namestr,"_avgD3");
  else
  sprintf(new_prefix,"%s%s",filename,"_avgD3");

  new_dsetavgD3 = EDIT_empty_copy( old_dset );

  { char * his = PLUTO_commandstring(plint) ;
  tross_Copy_History( old_dset , new_dsetavgD3 ) ;
  tross_Append_History( new_dsetavgD3 , his ) ; free(his) ;
  }

   	/*-- edit some of its internal parameters --*/

  ii = EDIT_dset_items(
        new_dsetavgD3 ,
          ADN_prefix      , new_prefix ,           /* filename prefix */
          ADN_malloc_type , DATABLOCK_MEM_MALLOC , /* store in memory */
          ADN_datum_all   , new_datum ,            /* atomic datum */
	  ADN_nvals	      , 1,
	  ADN_ntt	,1,
          ADN_none ) ;





   /*---------------------- make a new dataset ----------------------*/

/*-------------------making a new dataset------------------------------------*/





   /*------ make floating point output sub-bricks
            (only at the end will scale to byte or shorts)

            Output #ii at freq #kk will go into fout[kk][ii],
            for kk=0..nfreq-1, and for ii=0..nvox-1.          ------*/

   nvox = old_dset->daxes->nxx * old_dset->daxes->nyy * old_dset->daxes->nzz ;

   foutD3 = (float **) malloc( sizeof(float *) * nuse ) ;  /* ptrs to sub-bricks */
   foutA3 = (float **) malloc( sizeof(float *) * nuse ) ;  /* ptrs to sub-bricks */
   foutavgD3 = (float **) malloc( sizeof(float *) * 1 ) ;  /* ptrs to sub-bricks */


   if( foutD3 == NULL | foutA3 == NULL | foutavgD3 == NULL){
      THD_delete_3dim_dataset( new_dsetD3 , False ) ;
      THD_delete_3dim_dataset( new_dsetA3 , False ) ;
      THD_delete_3dim_dataset( new_dsetavgD3 , False ) ;
      FREE_WORKSPACE ;
      return "Malloc\nFailure!\n [fout]" ;
   }

   for( kk=0 ; kk < nfreq ; kk++ ){
      foutD3[kk] = (float *) malloc( sizeof(float) * nvox ) ; /* sub-brick # kk */
      foutA3[kk] = (float *) malloc( sizeof(float) * nvox ) ; /* sub-brick # kk */
      foutavgD3[0] = (float *) malloc( sizeof(float) * nvox ) ; /* sub-brick # kk */
      if( foutD3[kk] == NULL ) break ;
      if( foutA3[kk] == NULL ) break ;
      if( foutavgD3[0] == NULL ) break ;
   }

   if( kk < nfreq ){
      for( ; kk >= 0 ; kk-- ){
       FREEUP(foutD3[kk]) ;
       FREEUP(foutA3[kk]) ;
       FREEUP(foutavgD3[0]) ;
       }/* free all we did get */
      THD_delete_3dim_dataset( new_dsetD3 , False ) ;
      THD_delete_3dim_dataset( new_dsetA3 , False ) ;
      THD_delete_3dim_dataset( new_dsetavgD3 , False ) ;
      FREE_WORKSPACE ;
      return "Malloc\nFailure!\n [arrays]" ;
   }

   { char buf[128] ;
     ii = (nfreq * nvox * sizeof(float)) / (1024*1024) ;
     sprintf( buf , "  \n"
                    "*** 3D+time ASL a3/d3:\n"
                    "*** Using %d MBytes of workspace,\n "
                    "*** with # time points = %d\n" , ii,numT ) ;
     PLUTO_popup_transient( plint , buf ) ;
   }

   /*----------------------------------------------------*/
   /*----- Setup has ended.  Now do some real work. -----*/

   /***** loop over voxels *****/

/* *(flip)=scale; */

*(numAv)= nuse-ignore;

   for( ii=0 ; ii < nvox ; ii ++ ){  /* time series */

      switch( old_datum ){

	case MRI_byte:
            for( kk=0 ; kk < nuse ; kk++ ){
            	this[kk] =  bptr[kk][ii] ;
             }

         break ;

         case MRI_short:
            for( kk=0 ; kk < nuse ; kk++ ){
             this[kk] =  sptr[kk][ii] ;

            }
         break ;

         case MRI_float:
            for( kk=0 ; kk < nuse ; kk++ ){
             this[kk] =  fptr[kk][ii] ;

            }

         break ;
      }

      flip=scale*pow(-1,ignore+1);

      for( kk=0 ; kk < nuse-ignore ; kk++ ){

      		if (kk==nuse-1-ignore){
        		*(*(foutD3+kk)+ii)=
			flip*( *(this+kk+ignore-1)-*(this+kk+ignore) );

			*(*(foutA3+kk)+ii)=
			2*(*(this+kk+ignore-1)+*(this+kk+ignore));


			}
		else if (kk==0){
						/*D3 tag - control*/
        		*(*(foutD3+kk)+ii)=
			flip*( *(this+kk+ignore)-*(this+kk+ignore+1) );

			*(*(foutA3+kk)+ii)=
			2*(*(this+kk+ignore)+*(this+kk+ignore+1));

			}

		else{
			*(*(foutD3+kk)+ii)=
			flip*( 1*(*(this+kk+ignore-1))+-2*(*(this+kk+ignore))+1*(*(this+kk+ignore+1)) );

			*(*(foutA3+kk)+ii)=
			((*(this+kk+ignore-1))+2*(*(this+kk+ignore))+(*(this+kk+ignore+1)));

			flip=-1*flip;


			}


	}



      for( kk=0 ; kk < nuse-ignore ; kk++ )
     *(*(foutavgD3)+ii)= *(*(foutavgD3)+ii)+(*(*(foutD3+kk)+ii));

     *(*(foutavgD3)+ii)=*(*(foutavgD3)+ii) / (*(numAv));


      }

   DSET_unload( old_dset ) ;  /* don't need this no more */

   switch( new_datum ){

      /*** output is floats is the simplest:
           we just have to attach the fout bricks to the dataset ***/

      case MRI_float:
         for( kk=0 ; kk < nuse-ignore ; kk++ )
            EDIT_substitute_brick( new_dsetD3 , kk , MRI_float , foutD3[kk] ) ;
      break ;

      /*** output is shorts:
           we have to create a scaled sub-brick from fout ***/

      case MRI_short:{
         short * boutD3 ;
         float facD3 ;

         for( kk=0 ; kk < nuse-ignore ; kk++ ){  /* loop over sub-bricks */

            /*-- get output sub-brick --*/

            boutD3 = (short *) malloc( sizeof(short) * nvox ) ;
            if( boutD3 == NULL ){
               fprintf(stderr,"\nFinal malloc error in plug_power!\n\a") ;
               EXIT(1) ;
            }

            /*-- find scaling and then scale --*/

            facD3  = MCW_vol_amax( nvox,1,1 , MRI_float , foutD3[kk] ) ;
            if( facD3  > 0.0 ){
               facD3  = 32767.0 / facD3  ;
               EDIT_coerce_scale_type( nvox,facD3  ,
                                       MRI_float,foutD3[kk] , MRI_short,boutD3  ) ;
               facD3  = 1.0 / facD3  ;
            }

            free( foutD3[kk] ) ;  /* don't need this anymore */

            /*-- put output brick into dataset, and store scale factor --*/

            EDIT_substitute_brick( new_dsetD3 , kk , MRI_short , boutD3  ) ;
            tarD3 [kk] = facD3  ;


         }

         /*-- save scale factor array into dataset --*/

         EDIT_dset_items( new_dsetD3 , ADN_brick_fac , tarD3  , ADN_none ) ;

      }
      break ;

      /*** output is bytes (byte = unsigned char)
           we have to create a scaled sub-brick from fout ***/

      case MRI_byte:{
         byte * boutD3  ;
         float facD3  ;

         for( kk=0 ; kk < nuse-ignore ; kk++ ){  /* loop over sub-bricks */

            /*-- get output sub-brick --*/

            boutD3  = (byte *) malloc( sizeof(byte) * nvox ) ;
            if( boutD3  == NULL ){
               fprintf(stderr,"\nFinal malloc error in plug_power!\n\a") ;
               EXIT(1) ;
            }

            /*-- find scaling and then scale --*/

            facD3  = MCW_vol_amax( nvox,1,1 , MRI_float , foutD3[kk] ) ;
            if( facD3  > 0.0 ){
               facD3  = 255.0 / facD3  ;
               EDIT_coerce_scale_type( nvox,facD3  ,
                                       MRI_float,foutD3[kk] , MRI_byte,boutD3 ) ;
               facD3 = 1.0 / facD3  ;
            }

            free( foutD3[kk] ) ;  /* don't need this anymore */

            /*-- put output brick into dataset, and store scale factor --*/

            EDIT_substitute_brick( new_dsetD3 , kk , MRI_byte , boutD3  ) ;
            tarD3 [kk] = facD3  ;


         }

         /*-- save scale factor array into dataset --*/

         EDIT_dset_items( new_dsetD3 , ADN_brick_fac , tarD3  , ADN_none ) ;
      }
      break ;

   } /* end of switch on output data type */


   switch( new_datum ){

      /*** output is floats is the simplest:
           we just have to attach the fout bricks to the dataset ***/

      case MRI_float:
         for( kk=0 ; kk < nuse-ignore ; kk++ )
            EDIT_substitute_brick( new_dsetA3 , kk , MRI_float , foutA3[kk] ) ;
      break ;

      /*** output is shorts:
           we have to create a scaled sub-brick from fout ***/

      case MRI_short:{
         short * boutA3 ;
         float facA3 ;

         for( kk=0 ; kk < nuse-ignore ; kk++ ){  /* loop over sub-bricks */

            /*-- get output sub-brick --*/

            boutA3 = (short *) malloc( sizeof(short) * nvox ) ;
            if( boutA3 == NULL ){
               fprintf(stderr,"\nFinal malloc error in plug_power!\n\a") ;
               EXIT(1) ;
            }

            /*-- find scaling and then scale --*/

            facA3 = MCW_vol_amax( nvox,1,1 , MRI_float , foutA3[kk] ) ;
            if( facA3 > 0.0 ){
               facA3 = 32767.0 / facA3 ;
               EDIT_coerce_scale_type( nvox,facA3 ,
                                       MRI_float,foutA3[kk] , MRI_short,boutA3 ) ;
               facA3 = 1.0 / facA3 ;
            }

            free( foutA3[kk] ) ;  /* don't need this anymore */

            /*-- put output brick into dataset, and store scale factor --*/

            EDIT_substitute_brick( new_dsetA3 , kk , MRI_short , boutA3 ) ;
            tarA3[kk] = facA3 ;


         }

         /*-- save scale factor array into dataset --*/

         EDIT_dset_items( new_dsetA3 , ADN_brick_fac , tarA3 , ADN_none ) ;

      }
      break ;

      /*** output is bytes (byte = unsigned char)
           we have to create a scaled sub-brick from fout ***/

      case MRI_byte:{
         byte * boutA3 ;
         float facA3 ;

         for( kk=0 ; kk < nuse-ignore ; kk++ ){  /* loop over sub-bricks */

            /*-- get output sub-brick --*/

            boutA3 = (byte *) malloc( sizeof(byte) * nvox ) ;
            if( boutA3 == NULL ){
               fprintf(stderr,"\nFinal malloc error in plug_power!\n\a") ;
               EXIT(1) ;
            }

            /*-- find scaling and then scale --*/

            facA3 = MCW_vol_amax( nvox,1,1 , MRI_float , foutA3[kk] ) ;
            if( facA3 > 0.0 ){
               facA3 = 255.0 / facA3 ;
               EDIT_coerce_scale_type( nvox,facA3 ,
                                       MRI_float,foutA3[kk] , MRI_byte,boutA3 ) ;
               facA3 = 1.0 / facA3 ;
            }

            free( foutA3[kk] ) ;  /* don't need this anymore */

            /*-- put output brick into dataset, and store scale factor --*/

            EDIT_substitute_brick( new_dsetA3 , kk , MRI_byte , boutA3 ) ;
            tarA3[kk]= facA3 ;


         }

         /*-- save scale factor array into dataset --*/

         EDIT_dset_items( new_dsetA3 , ADN_brick_fac , tarA3 , ADN_none ) ;
      }
      break ;

   } /* end of switch on output data type */


     switch( new_datum ){

      case MRI_float:{

            EDIT_substitute_brick( new_dsetavgD3 , 0 , MRI_float , foutavgD3[0] ) ;


    }
      break ;

      case MRI_short:{
         short * boutavgD3 ;
         float facavgD3 ;

            boutavgD3 = (short *) malloc( sizeof(short) * nvox ) ;
            if( boutavgD3 == NULL ){
               fprintf(stderr,"\nFinal malloc error in plug_power!\n\a") ;
               EXIT(1) ;
            }

            facavgD3 = MCW_vol_amax( nvox,1,1 , MRI_float , foutavgD3[0] ) ;
            if( facavgD3 > 0.0 ){
               facavgD3 = 32767.0 / facavgD3 ;
               EDIT_coerce_scale_type( nvox,facavgD3 ,
                                       MRI_float,foutavgD3[0] , MRI_short,boutavgD3 ) ;
               facavgD3 = 1.0 / facavgD3 ;
            }



            EDIT_substitute_brick( new_dsetavgD3 , 0 , MRI_short , boutavgD3 ) ;
            taravgD3[0] = facavgD3 ;

             EDIT_dset_items( new_dsetavgD3 , ADN_brick_fac , taravgD3 , ADN_none ) ;



      }
      break ;

      case MRI_byte:{
         byte * boutavgD3 ;
         float facavgD3 ;


            boutavgD3 = (byte *) malloc( sizeof(byte) * nvox ) ;
            if( boutavgD3 == NULL ){
               fprintf(stderr,"\nFinal malloc error in plug_power!\n\a") ;
               EXIT(1) ;
            }

            facavgD3 = MCW_vol_amax( nvox,1,1 , MRI_float , foutavgD3[0] ) ;
            if( facavgD3 > 0.0 ){
               facavgD3 = 255.0 / facavgD3 ;
               EDIT_coerce_scale_type( nvox,facavgD3 ,
                                       MRI_float,foutavgD3[0] , MRI_byte,boutavgD3 ) ;
               facavgD3 = 1.0 / facavgD3 ;
            }



            EDIT_substitute_brick( new_dsetavgD3 , 0 , MRI_byte , boutavgD3 ) ;
            taravgD3[0]= facavgD3 ;

            EDIT_dset_items( new_dsetavgD3 , ADN_brick_fac , taravgD3 , ADN_none ) ;




      }
      break ;

   } /* endasda of switch on output data type */




   /*-------------- Cleanup and go home ----------------*/



   PLUTO_add_dset( plint , new_dsetD3 , DSET_ACTION_NONE ) ;
  PLUTO_add_dset( plint , new_dsetA3 , DSET_ACTION_NONE ) ;
  PLUTO_add_dset( plint , new_dsetavgD3 , DSET_ACTION_NONE ) ;



   FREE_WORKSPACE ;
   free(numAv);


   return NULL ;  /* null string returned means all was OK */
}
Exemple #13
0
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *dset_in=NULL , *dset_out ;
   int Lxx=-1 , Lyy=-1 , Lzz=-1 , Mode=FFT_ABS , Sign=-1 , do_alt=0 ;
   char *prefix = "FFTout" ;
   int iarg ;
   MRI_IMAGE *inim , *outim ; float fac ; int nx,ny,nz ;
   THD_ivec3 iv ;

   if( argc < 2 || strcasecmp(argv[1],"-help") == 0 ){
     printf(
       "Usage: 3dFFT [options] dataset\n"
       "\n"
       "* Does the FFT of the input dataset in 3 directions (x,y,z) and\n"
       "   produces the output dataset.\n"
       "\n"
       "* Why you'd want to do this is an interesting question.\n"
       "\n"
       "* Program 3dcalc can operate on complex-valued datasets, but\n"
       "   only on one component at a time (cf. the '-cx2r' option).\n"
       "\n"
       "* Most other AFNI programs can only operate on real-valued\n"
       "   datasets.\n"
       "\n"
       "* You could use 3dcalc (twice) to split a complex-valued dataset\n"
       "   into two real-valued datasets, do your will on those with other\n"
       "   AFNI programs, then merge the results back into a complex-valued\n"
       "   dataset with 3dTwotoComplex.\n"
       "\n"
       "Options\n"
       "=======\n"
       " -abs       = Outputs the magnitude of the FFT [default]\n"
       " -phase     = Outputs the phase of the FFT (-PI..PI == no unwrapping!)\n"
       " -complex   = Outputs the complex-valued FFT\n"
       " -inverse   = Does the inverse FFT instead of the forward FFT\n"
       "\n"
       " -Lx xx     = Use FFT of length 'xx' in the x-direction\n"
       " -Ly yy     = Use FFT of length 'yy' in the y-direction\n"
       " -Lz zz     = Use FFT of length 'zz' in the z-direction\n"
       "              * Set a length to 0 to skip the FFT in that direction\n"
       "\n"
       " -altIN     = Alternate signs of input data before FFT, to bring\n"
       "               zero frequency from edge of FFT-space to center of grid\n"
       "               for cosmetic purposes.\n"
       " -altOUT    = Alternate signs of output data after FFT.  If you\n"
       "               use '-altI' on the forward transform, then you should\n"
       "               use '-altO' an the inverse transform, to get the\n"
       "               signs of the recovered image correct.\n"
       "      **N.B.: You cannot use '-altIN' and '-altOUT' in the same run!\n"
       "\n"
       " -input dd  = Read the input dataset from 'dd', instead of\n"
       "               from the last argument on the command line.\n"
       "\n"
       " -prefix pp = Use 'pp' for the output dataset prefix.\n"
       "\n"
       "Notes\n"
       "=====\n"
       " * In the present avatar, only 1 sub-brick will be processed.\n"
       "\n"
       " * The program can only do FFT lengths that are factorable\n"
       "    into a product of powers of 2, 3, and 5, and are even.\n"
       "   + The largest power of 3 that is allowed is 3^3 = 27.\n"
       "   + The largest power of 5 that is allowed is 5^3 = 125.\n"
       "   + e.g., FFT of length 3*5*8=120 is possible.\n"
       "   + e.g., FFT of length 4*31 =124 is not possible.\n"
       "\n"
       " * The 'x', 'y', and 'z' axes here refer to the order the\n"
       "    data is stored, not DICOM coordinates; cf. 3dinfo.\n"
       "\n"
       " * If you force (via '-Lx' etc.) an FFT length that is not\n"
       "    allowed, the program will stop with an error message.\n"
       "\n"
       " * If you force an FFT length that is shorter than an dataset\n"
       "    axis dimension, the program will stop with an error message.\n"
       "\n"
       " * If you don't force an FFT length along a particular axis,\n"
       "    the program will pick the smallest legal value that is\n"
       "    greater than or equal to the corresponding dataset dimension.\n"
       "   + e.g., 124 would be increased to 128.\n"
       "\n"
       " * If an FFT length is longer than an axis length, then the\n"
       "    input data in that direction is zero-padded at the end.\n"
       "\n"
       " * For -abs and -phase, the output dataset is in float format.\n"
       "\n"
       " * If you do the forward and inverse FFT, then you should get back\n"
       "    the original dataset, except for roundoff error and except that\n"
       "    the new dataset axis dimensions may be longer than the original.\n"
       "\n"
       " * Forward FFT = sum_{k=0..N-1} [ exp(-2*PI*i*k/N) * data(k) ]\n"
       "\n"
       " * Inverse FFT = sum_{k=0..N-1} [ exp(+2*PI*i*k/N) * data(k) ] / N\n"
       "\n"
       " * Started a long time ago, but only finished in Aug 2009 at the\n"
       "    request of John Butman, because he asked so nicely.  (Now pay up!)\n"
     ) ;
     PRINT_COMPILE_DATE ; exit(0) ;
   }

   PRINT_VERSION("3dFFT") ;
   mainENTRY("3dFFT main") ; machdep() ; AUTHOR("RW Cox") ;
   AFNI_logger("3dFFT",argc,argv) ;

   /*--- scan args ---*/

   iarg = 1 ;

   while( iarg < argc && argv[iarg][0] == '-' ){

     if( strncasecmp(argv[iarg],"-altI",5) == 0 ){
       do_alt = 1 ; iarg++ ; continue ;
     }
     if( strncasecmp(argv[iarg],"-altOUT",5) == 0 ){
       do_alt = -1 ; iarg++ ; continue ;
     }
     if( strncasecmp(argv[iarg],"-inverse",4) == 0 ){
       Sign = +1 ; iarg++ ; continue ;
     }
     if( strncasecmp(argv[iarg],"-abs",4) == 0 ){
       Mode = FFT_ABS ; iarg++ ; continue ;
     }
     if( strncasecmp(argv[iarg],"-phase",4) == 0 ){
       Mode = FFT_PHASE ; iarg++ ; continue ;
     }
     if( strncasecmp(argv[iarg],"-complex",4) == 0 ){
       Mode = FFT_COMPLEX ; iarg++ ; continue ;
     }

     if( strlen(argv[iarg]) == 3 && strncmp(argv[iarg],"-L",2) == 0 ){
       int lll=-1 , mmm ; char *ept ;
       iarg++ ;
       if( iarg >= argc )
         ERROR_exit("need an argument after option %s",argv[iarg-1]) ;

       lll = strtol( argv[iarg] , &ept , 10 ) ;
       if( *ept != '\0' )
         ERROR_exit("bad argument after option %s",argv[iarg-1]) ;
       if( lll > 0 && (mmm = csfft_nextup_even(lll)) != lll )
         ERROR_exit(
          "'%s %d' is not a legal FFT length here: next largest legal value = %d" ,
          argv[iarg-1] , lll , mmm ) ;
       switch( argv[iarg-1][2] ){
         case 'x': case 'X': Lxx = lll ; break ;
         case 'y': case 'Y': Lyy = lll ; break ;
         case 'z': case 'Z': Lzz = lll ; break ;
         default:  ERROR_exit("unknown option '%s'",argv[iarg-1]) ;
       }
       iarg++ ; continue ;
     }

     if( strncasecmp(argv[iarg],"-prefix",4) == 0 ){
       iarg++ ;
       if( iarg >= argc )
         ERROR_exit("need an argument after %s\n",argv[iarg-1]) ;
       prefix = strdup( argv[iarg] ) ;
       if( !THD_filename_ok(prefix) )
         ERROR_exit("bad argument after %s\n",argv[iarg-1]) ;
       iarg++ ; continue ;
     }

     if( strncasecmp(argv[iarg],"-input",4) == 0 ){
       iarg++ ;
       if( iarg >= argc )
         ERROR_exit("need an argument after %s\n",argv[iarg-1]) ;
       dset_in = THD_open_dataset(argv[iarg]); CHECK_OPEN_ERROR(dset_in,argv[iarg]);
       iarg++ ; continue ;
     }

     ERROR_exit("unknown option '%s'\n",argv[iarg]) ;
   }

   /* check for simple errors */

   if( Lxx == 0 && Lyy == 0 && Lzz == 0 )
     ERROR_exit("-Lx, -Ly, -Lz all given as zero?!") ;

   /* open input dataset */

   if( dset_in == NULL ){
     if( iarg >= argc ) ERROR_exit("no input dataset on command line?!\n") ;
     dset_in = THD_open_dataset(argv[iarg]); CHECK_OPEN_ERROR(dset_in,argv[iarg]);
   }

   nx = DSET_NX(dset_in) ; ny = DSET_NY(dset_in) ; nz = DSET_NZ(dset_in) ;

   if( DSET_NVALS(dset_in) > 1 )
     WARNING_message("only 3dFFT-ing sub-brick #0 of input dataset") ;

   /* establish actual FFT lengths now (0 ==> no FFT) */

   if( nx == 1 ) Lxx = 0 ;  /* can't FFT if dataset is shrimpy! */
   if( ny == 1 ) Lyy = 0 ;
   if( nz == 1 ) Lzz = 0 ;

   if( Lxx < 0 ) Lxx = csfft_nextup_even(nx) ;  /* get FFT length from */
   if( Lyy < 0 ) Lyy = csfft_nextup_even(ny) ;  /* dataset dimensions */
   if( Lzz < 0 ) Lzz = csfft_nextup_even(nz) ;

   INFO_message("x-axis length=%d ; FFT length=%d %s",nx,Lxx,(Lxx==0)?"==> none":"\0") ;
   INFO_message("y-axis length=%d ; FFT length=%d %s",ny,Lyy,(Lyy==0)?"==> none":"\0") ;
   INFO_message("z-axis length=%d ; FFT length=%d %s",nz,Lzz,(Lzz==0)?"==> none":"\0") ;

   if( Lxx > 0 && Lxx < nx ) ERROR_exit("x-axis FFT length too short for data!") ;
   if( Lyy > 0 && Lyy < ny ) ERROR_exit("y-axis FFT length too short for data!") ;
   if( Lzz > 0 && Lzz < nz ) ERROR_exit("z-axis FFT length too short for data!") ;

   /* extract sub-brick #0 */

   DSET_load(dset_in) ; CHECK_LOAD_ERROR(dset_in) ;

   inim = mri_to_complex( DSET_BRICK(dset_in,0) ) ; /* convert input to complex */
   fac  = DSET_BRICK_FACTOR(dset_in,0) ;
   if( fac > 0.0f && fac != 1.0f ){                 /* scale it if needed */
     int ii , nvox = nx*ny*nz ; complex *car = MRI_COMPLEX_PTR(inim) ;
     for( ii=0 ; ii < nvox ; ii++ ){ car[ii].r *= fac ; car[ii].i *= fac ; }
   }

   DSET_unload(dset_in) ;  /* input data is all copied now */

   /* FFT to get output image */

   csfft_scale_inverse(1) ;  /* scale by 1/N for inverse FFTs */

   outim = mri_fft_3D( Sign , inim , Lxx,Lyy,Lzz , do_alt ) ;

   mri_free(inim) ;

   /* post-process output? */

   switch( Mode ){
     case FFT_ABS:{
       MRI_IMAGE *qim = mri_complex_abs(outim) ;
       mri_free(outim) ; outim = qim ;
     }
     break ;

     case FFT_PHASE:{
       MRI_IMAGE *qim = mri_complex_phase(outim) ;
       mri_free(outim) ; outim = qim ;
     }
     break ;
   }

   /* create and write output dataset */

   dset_out = EDIT_empty_copy( dset_in ) ;
   tross_Copy_History( dset_in , dset_out ) ;
   tross_Make_History( "3dFFT" , argc,argv , dset_out ) ;
   LOAD_IVEC3( iv , outim->nx , outim->ny , outim->nz ) ;
   EDIT_dset_items( dset_out ,
                      ADN_prefix , prefix ,
                      ADN_nvals  , 1 ,
                      ADN_ntt    , 0 ,
                      ADN_nxyz   , iv ,  /* change dimensions, possibly */
                    ADN_none ) ;
   EDIT_BRICK_FACTOR( dset_out , 0 , 0.0 ) ;
   EDIT_substitute_brick( dset_out , 0 , outim->kind , mri_data_pointer(outim) ) ;
   DSET_write(dset_out) ; WROTE_DSET(dset_out) ; DSET_unload(dset_out) ;

   exit(0) ;
}
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *dset ;
   char *prefix ;
   int narg=1 ;

#ifndef DONT_ALLOW_MINC

WARNING_message("This program (3dMINCtoAFNI) is old, obsolete, and not maintained!") ;

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
      printf("Usage: 3dMINCtoAFNI [-prefix ppp] dataset.mnc\n"
             "Reads in a MINC formatted file and writes it out as an\n"
             "AFNI dataset file pair with the given prefix.  If the\n"
             "prefix option isn't used, the input filename will be\n"
             "used, after the '.mnc' is chopped off.\n"
             "\n"
             "NOTES:\n"
             "* Setting environment variable AFNI_MINC_FLOATIZE to Yes\n"
             "   will cause MINC datasets to be converted to floats on\n"
             "   input.  Otherwise, they will be kept in their 'native'\n"
             "   data type if possible, which may cause problems with\n"
             "   scaling on occasion.\n"
             "* The TR recorded in MINC files is often incorrect.  You may\n"
             "   need to fix this (or other parameters) using 3drefit.\n"
            ) ;
      PRINT_COMPILE_DATE ; exit(0) ;
   }

   if( strcmp(argv[narg],"-prefix") == 0 ){
      prefix = argv[++narg] ;
      if( !THD_filename_ok(prefix) ){
         fprintf(stderr,"** Prefix string is illegal: %s\n",prefix) ;
         exit(1) ;
      }
      narg++ ;
   } else {
      int ii ;
      prefix = strdup(argv[narg]) ;
      ii = strlen(prefix) ;
      if( ii > 5 ) prefix[ii-4] = '\0' ;
      if( !THD_filename_ok(prefix) ){
         fprintf(stderr,"** Prefix string is illegal: %s\n",prefix) ;
         exit(1) ;
      }
   }

   dset = THD_open_minc( argv[narg] ) ;
   if( dset == NULL ){
      fprintf(stderr,"** Can't open dataset %s\n",argv[narg]) ;
      exit(1) ;
   }
   if( !DSET_IS_MINC(dset) ){
      fprintf(stderr,"** Not a MINC dataset: %s\n",argv[narg]) ;
      exit(1) ;
   }
   DSET_load(dset) ; CHECK_LOAD_ERROR(dset) ;

   EDIT_dset_items( dset , ADN_prefix,prefix , ADN_none ) ;
   dset->idcode = MCW_new_idcode() ;

   dset->dblk->diskptr->storage_mode = STORAGE_BY_BRICK ;

   tross_Make_History( "3dMINCtoAFNI" , argc,argv , dset ) ;

   DSET_write(dset) ;
   fprintf(stderr,"++ Wrote dataset %s\n",DSET_BRIKNAME(dset)) ;
   exit(0) ;

#else
   ERROR_exit("3dMINCtoAFNI is no longer compiled") ;
#endif
}
Exemple #15
0
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *old_dset , *new_dset ;  /* input and output datasets */
   THD_3dim_dataset *mask_dset=NULL  ;
   float mask_bot=666.0 , mask_top=-666.0 ;
   byte *cmask=NULL ; int ncmask=0 ;
   byte *mmm   = NULL ;
   int mcount=0, verb=0;
   int nopt, nbriks, ii ;
   int addBriks = 0 ;   /* n-1 sub-bricks out */
   int fullBriks = 0 ;  /* n   sub-bricks out */
   int tsout = 0 ;      /* flag to output a time series (not a stat bucket) */
   int numMultBriks,methIndex,brikIndex;

   /*----- Help the pitiful user? -----*/


   /* bureaucracy */
   mainENTRY("3dTstat main"); machdep(); AFNI_logger("3dTstat",argc,argv);
   PRINT_VERSION("3dTstat"); AUTHOR("KR Hammett & RW Cox");

   /*--- scan command line for options ---*/

   if (argc == 1) { usage_3dTstat(1); exit(0); } /* Bob's help shortcut */
   nopt = 1 ;
   nbriks = 0 ;
   nmeths = 0 ;
   verb = 0;
   while( nopt < argc && argv[nopt][0] == '-' ){
      if (strcmp(argv[nopt], "-h") == 0 || strcmp(argv[nopt], "-help") == 0) {
         usage_3dTstat(strlen(argv[nopt]) > 3 ? 2:1);
         exit(0);
      }

      if( strcmp(argv[nopt],"-verb") == 0 ){
        verb++ ; nopt++ ; continue ;
      }
      
      /*-- methods --*/

      if( strcasecmp(argv[nopt],"-centromean") == 0 ){ /* 01 Nov 2010 */
         meth[nmeths++] = METH_CENTROMEAN ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-bmv") == 0 ){
         meth[nmeths++] = METH_BMV ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-median") == 0 ){
         meth[nmeths++] = METH_MEDIAN ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-nzmedian") == 0 ){
         meth[nmeths++] = METH_NZMEDIAN ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-DW") == 0 ){
         meth[nmeths++] = METH_DW ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-zcount") == 0 ){
         meth[nmeths++] = METH_ZCOUNT ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-nzcount") == 0 ){
         meth[nmeths++] = METH_NZCOUNT ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-MAD") == 0 ){
         meth[nmeths++] = METH_MAD ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-mean") == 0 ){
         meth[nmeths++] = METH_MEAN ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-sum") == 0 ){
         meth[nmeths++] = METH_SUM ;
         nbriks++ ;
         nopt++ ; continue ;
      }
      if( strcasecmp(argv[nopt],"-sos") == 0 ){
         meth[nmeths++] = METH_SUM_SQUARES ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-abssum") == 0 ){
         meth[nmeths++] = METH_ABSSUM ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-slope") == 0 ){
         meth[nmeths++] = METH_SLOPE ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-stdev") == 0 ||
          strcasecmp(argv[nopt],"-sigma") == 0   ){

         meth[nmeths++] = METH_SIGMA ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-cvar") == 0 ){
         meth[nmeths++] = METH_CVAR ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-cvarinv") == 0 ){
         meth[nmeths++] = METH_CVARINV ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-stdevNOD") == 0 ||
          strcasecmp(argv[nopt],"-sigmaNOD") == 0   ){  /* 07 Dec 2001 */

         meth[nmeths++] = METH_SIGMA_NOD ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-cvarNOD") == 0 ){     /* 07 Dec 2001 */
         meth[nmeths++] = METH_CVAR_NOD ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-cvarinvNOD") == 0 ){
         meth[nmeths++] = METH_CVARINVNOD ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-min") == 0 ){
         meth[nmeths++] = METH_MIN ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-max") == 0 ){
         meth[nmeths++] = METH_MAX ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-absmax") == 0 ){
         meth[nmeths++] = METH_ABSMAX ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-signed_absmax") == 0 ){
         meth[nmeths++] = METH_SIGNED_ABSMAX ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-argmin") == 0 ){
         meth[nmeths++] = METH_ARGMIN ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-argmin1") == 0 ){
         meth[nmeths++] = METH_ARGMIN1 ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-argmax") == 0 ){
         meth[nmeths++] = METH_ARGMAX ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-argmax1") == 0 ){
         meth[nmeths++] = METH_ARGMAX1 ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-argabsmax") == 0 ){
         meth[nmeths++] = METH_ARGABSMAX ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-argabsmax1") == 0 ){
         meth[nmeths++] = METH_ARGABSMAX1;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-duration") == 0 ){
         meth[nmeths++] = METH_DURATION ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-onset") == 0 ){
         meth[nmeths++] = METH_ONSET ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-offset") == 0 ){
         meth[nmeths++] = METH_OFFSET ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-centroid") == 0 ){
         meth[nmeths++] = METH_CENTROID ;
         nbriks++ ;
         nopt++ ; continue ;
      }
      if( strcasecmp(argv[nopt],"-centduration") == 0 ){
         meth[nmeths++] = METH_CENTDURATION ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-nzmean") == 0 ){
         meth[nmeths++] = METH_NZMEAN ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      if( strncmp(argv[nopt],"-mask",5) == 0 ){
         if( mask_dset != NULL )
           ERROR_exit("Cannot have two -mask options!\n") ;
         if( nopt+1 >= argc )
           ERROR_exit("-mask option requires a following argument!\n");
         mask_dset = THD_open_dataset( argv[++nopt] ) ;
         if( mask_dset == NULL )
           ERROR_exit("Cannot open mask dataset!\n") ;
         if( DSET_BRICK_TYPE(mask_dset,0) == MRI_complex )
           ERROR_exit("Cannot deal with complex-valued mask dataset!\n");
         nopt++ ; continue ;
      }

      if( strncmp(argv[nopt],"-mrange",5) == 0 ){
         if( nopt+2 >= argc )
           ERROR_exit("-mrange option requires 2 following arguments!\n");
         mask_bot = strtod( argv[++nopt] , NULL ) ;
         mask_top = strtod( argv[++nopt] , NULL ) ;
         if( mask_top < mask_top )
           ERROR_exit("-mrange inputs are illegal!\n") ;
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-cmask") == 0 ){  /* 16 Mar 2000 */
         if( nopt+1 >= argc )
            ERROR_exit("-cmask option requires a following argument!\n");
         cmask = EDT_calcmask( argv[++nopt] , &ncmask, 0 ) ;
         if( cmask == NULL ) ERROR_exit("Can't compute -cmask!\n");
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-autocorr") == 0 ){
         meth[nmeths++] = METH_AUTOCORR ;
         if( ++nopt >= argc ) ERROR_exit("-autocorr needs an argument!\n");
         meth[nmeths++] = atoi(argv[nopt++]);
         if (meth[nmeths - 1] == 0) {
           addBriks++;
         } else {
           nbriks+=meth[nmeths - 1] ;
         }
         continue ;
      }

      if( strcasecmp(argv[nopt],"-autoreg") == 0 ){
         meth[nmeths++] = METH_AUTOREGP ;
         if( ++nopt >= argc ) ERROR_exit("-autoreg needs an argument!\n");
         meth[nmeths++] = atoi(argv[nopt++]);
         if (meth[nmeths - 1] == 0) {
           addBriks++;
         } else {
           nbriks+=meth[nmeths - 1] ;
         }
         continue ;
      }

      if( strcasecmp(argv[nopt],"-accumulate") == 0 ){  /* 4 Mar 2008 [rickr] */
         meth[nmeths++] = METH_ACCUMULATE ;
         meth[nmeths++] = -1;   /* flag to add N (not N-1) output bricks */
         fullBriks++;
         tsout = 1;             /* flag to output a timeseries */
         nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-l2norm") == 0 ){  /* 07 Jan 2013 [rickr] */
         meth[nmeths++] = METH_L2_NORM ;
         nbriks++ ;
         nopt++ ; continue ;
      }

      /*-- prefix --*/

      if( strcasecmp(argv[nopt],"-prefix") == 0 ){
         if( ++nopt >= argc ) ERROR_exit("-prefix needs an argument!\n");
         MCW_strncpy(prefix,argv[nopt],THD_MAX_PREFIX) ;
         if( !THD_filename_ok(prefix) )
           ERROR_exit("%s is not a valid prefix!\n",prefix);
         nopt++ ; continue ;
      }

      /*-- tdiff --*/

      if( strcasecmp(argv[nopt],"-tdiff") == 0 ){  /* 25 May 2011 */
        do_tdiff = 1 ; nopt++ ; continue ;
      }

      /*-- nscale --*/

      if( strcasecmp(argv[nopt],"-nscale") == 0 ){  /* 25 May 2011 */
        nscale = 1 ; nopt++ ; continue ;
      }
      
      /*-- datum --*/

      if( strcasecmp(argv[nopt],"-datum") == 0 ){
         if( ++nopt >= argc ) ERROR_exit("-datum needs an argument!\n");
         if( strcasecmp(argv[nopt],"short") == 0 ){
            datum = MRI_short ;
         } else if( strcasecmp(argv[nopt],"float") == 0 ){
            datum = MRI_float ;
         } else if( strcasecmp(argv[nopt],"byte") == 0 ){
            datum = MRI_byte ;
         } else {
            ERROR_exit("-datum of type '%s' is not supported!\n",
                       argv[nopt] ) ;
         }
         nopt++ ; continue ;
      }

     /* base percentage for duration calcs */
     if (strcasecmp (argv[nopt], "-basepercent") == 0) {
         if( ++nopt >= argc ) ERROR_exit("-basepercent needs an argument!\n");
         basepercent = strtod(argv[nopt], NULL);
         if(basepercent>1) basepercent /= 100.0;  /* assume integer percent if >1*/
         nopt++;  continue;
        }

      /*-- Quien sabe'? --*/

      ERROR_message("Unknown option: %s\n",argv[nopt]) ;
      suggest_best_prog_option(argv[0], argv[nopt]);
      exit(1);
   }

    if (argc < 2) {
      ERROR_message("Too few options, use -help for details");
      exit(1);
    }

   /*--- If no options selected, default to single stat MEAN -- KRH ---*/

   if (nmeths == 0) nmeths = 1;
   if (nbriks == 0 && addBriks == 0 && fullBriks == 0) nbriks = 1;

   /*----- read input dataset -----*/

   if( nopt >= argc ) ERROR_exit(" No input dataset!?") ;

   old_dset = THD_open_dataset( argv[nopt] ) ;
   if( !ISVALID_DSET(old_dset) )
     ERROR_exit("Can't open dataset %s\n",argv[nopt]);

   nopt++ ;
   if( nopt < argc )
     WARNING_message("Trailing datasets on command line ignored: %s ...",argv[nopt]) ;

   if( DSET_NVALS(old_dset) == 1 ){
     WARNING_message("Input dataset has 1 sub-brick ==> -tdiff is turned off") ;
     do_tdiff = 0 ;
   }

   /* no input volumes is bad, 1 volume applies to only certain methods */
   /*                                                2 Nov 2010 [rickr] */
   if( DSET_NVALS(old_dset) == 0 ) {
      ERROR_exit("Time series is of length 0?\n") ;
   }
   else if( DSET_NVALS(old_dset) == 1 || (do_tdiff && DSET_NVALS(old_dset)==2) ) {
     int methOK, OK = 1;
     /* see if each method is valid for nvals == 1 */
     for( methIndex = 0; methIndex < nmeths; methIndex++ ) {
        methOK = 0;
        for( ii = 0; ii < NUM_1_INPUT_METHODS; ii++ ) {
            if( meth[methIndex] == valid_1_input_methods[ii] ) {
                methOK = 1;
                break;
            }
        }
        if( ! methOK )
           ERROR_exit("Can't use dataset with %d values per voxel!" ,
                      DSET_NVALS(old_dset) ) ;
     }
     /* tell the library function that this case is okay */
     g_thd_maker_allow_1brick = 1;
   }

   if( DSET_NUM_TIMES(old_dset) < 2 ){
     WARNING_message("Input dataset is not 3D+time; assuming TR=1.0") ;
     EDIT_dset_items( old_dset ,
                        ADN_ntt    , DSET_NVALS(old_dset) ,
                        ADN_ttorg  , 0.0 ,
                        ADN_ttdel  , 1.0 ,
                        ADN_tunits , UNITS_SEC_TYPE ,
                      NULL ) ;
   }

   /* If one or more of the -autocorr/-autoreg options was called with */
   /* an argument of 0, then I'll now add extra BRIKs for the N-1 data */
   /* output points for each.                                          */
   nbriks += ((DSET_NVALS(old_dset)-1) * addBriks);
   nbriks += ((DSET_NVALS(old_dset)  ) * fullBriks);

   /* ------------- Mask business -----------------*/
   if( mask_dset == NULL ){
      mmm = NULL ;
      if( verb )
         INFO_message("%d voxels in the entire dataset (no mask)\n",
                     DSET_NVOX(old_dset)) ;
   } else {
      if( DSET_NVOX(mask_dset) != DSET_NVOX(old_dset) )
        ERROR_exit("Input and mask datasets are not same dimensions!\n");
      mmm = THD_makemask( mask_dset , 0 , mask_bot, mask_top ) ;
      mcount = THD_countmask( DSET_NVOX(old_dset) , mmm ) ;
      if( mcount <= 0 ) ERROR_exit("No voxels in the mask!\n") ;
      if( verb ) INFO_message("%d voxels in the mask\n",mcount) ;
      DSET_delete(mask_dset) ;
   }

   if( cmask != NULL ){
      if( ncmask != DSET_NVOX(old_dset) )
        ERROR_exit("Input and cmask datasets are not same dimensions!\n");
      if( mmm != NULL ){
         for( ii=0 ; ii < DSET_NVOX(old_dset) ; ii++ )
            mmm[ii] = (mmm[ii] && cmask[ii]) ;
         free(cmask) ;
         mcount = THD_countmask( DSET_NVOX(old_dset) , mmm ) ;
         if( mcount <= 0 ) ERROR_exit("No voxels in the mask+cmask!\n") ;
         if( verb ) INFO_message("%d voxels in the mask+cmask\n",mcount) ;
      } else {
         mmm = cmask ;
         mcount = THD_countmask( DSET_NVOX(old_dset) , mmm ) ;
         if( mcount <= 0 ) ERROR_exit("No voxels in the cmask!\n") ;
         if( verb ) INFO_message("%d voxels in the cmask\n",mcount) ;
      }
   }

   /*------------- ready to compute new dataset -----------*/

   new_dset = MAKER_4D_to_typed_fbuc(
                 old_dset ,             /* input dataset */
                 prefix ,               /* output prefix */
                 datum ,                /* output datum  */
                 0 ,                    /* ignore count  */
                 0 ,              /* can't detrend in maker function  KRH 12/02*/
                 nbriks ,               /* number of briks */
                 STATS_tsfunc ,         /* timeseries processor */
                 NULL,                  /* data for tsfunc */
                 mmm,
                 nscale
              ) ;

   if( new_dset != NULL ){
      tross_Copy_History( old_dset , new_dset ) ;
      tross_Make_History( "3dTstat" , argc,argv , new_dset ) ;
      for (methIndex = 0,brikIndex = 0; methIndex < nmeths;
           methIndex++, brikIndex++) {
        if ((meth[methIndex] == METH_AUTOCORR)   ||
            (meth[methIndex] == METH_ACCUMULATE) ||
            (meth[methIndex] == METH_AUTOREGP)) {
          numMultBriks = meth[methIndex+1];

          /* note: this looks like it should be NV-1   4 Mar 2008 [rickr] */
          if (numMultBriks ==  0) numMultBriks = DSET_NVALS(old_dset)-1;
          /* new flag for NVALS [rickr] */
          if (numMultBriks == -1) numMultBriks = DSET_NVALS(old_dset);

          for (ii = 1; ii <= numMultBriks; ii++) {
            char tmpstr[25];
            if (meth[methIndex] == METH_AUTOREGP) {
              sprintf(tmpstr,"%s[%d](%d)",meth_names[meth[methIndex]],
                      numMultBriks,ii);
            } else {
              sprintf(tmpstr,"%s(%d)",meth_names[meth[methIndex]],ii);
            }
            EDIT_BRICK_LABEL(new_dset, (brikIndex + ii - 1), tmpstr) ;
          }
          methIndex++;
          brikIndex += numMultBriks - 1;
        } else {
          EDIT_BRICK_LABEL(new_dset, brikIndex, meth_names[meth[methIndex]]) ;
        }
      }

      if( tsout ) /* then change output to a time series */
         EDIT_dset_items( new_dset ,
                        ADN_ntt    , brikIndex ,
                        ADN_ttorg  , DSET_TIMEORIGIN(old_dset) ,
                        ADN_ttdel  , DSET_TIMESTEP(old_dset) ,
                        ADN_tunits , DSET_TIMEUNITS(old_dset) ,
                      NULL ) ;

      DSET_write( new_dset ) ;
      WROTE_DSET( new_dset ) ;
   } else {
      ERROR_exit("Unable to compute output dataset!\n") ;
   }

   exit(0) ;
}
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *inset=NULL , *outset ;
   THD_3dim_dataset **insar=NULL ; int nsar=0 ;
   int iarg=1 , ii,kk , ids ;
   MCW_cluster *nbhd=NULL ;
   char *prefix="./localhistog" ;
   int ntype=0 ; float na=0.0f,nb=0.0f,nc=0.0f ;
   int verb=1 , do_prob=0 ;
   int nx=0,ny=0,nz=0,nvox=0, rbot,rtop ;
   char *labfile=NULL ; NI_element *labnel=NULL ;
   int nlab=0 , *labval=NULL ; char **lablab=NULL ; char buf[THD_MAX_SBLABEL] ;
   UINT32 *ohist , *mhist=NULL ; char *ohist_name=NULL ; int ohzadd=0 ;
   int *rlist , numval ; float mincount=0.0f ; int mcc ;
   int *exlist=NULL, numex=0 ;
   int do_excNONLAB=0 ;

   /*---- for the clueless who wish to become clued-in ----*/

   if( argc == 1 ){ usage_3dLocalHistog(1); exit(0); } /* Bob's help shortcut */

   /*---- official startup ---*/

#if defined(USING_MCW_MALLOC) && !defined(USE_OMP)
   enable_mcw_malloc() ;
#endif

   PRINT_VERSION("3dLocalHistog"); mainENTRY("3dLocalHistog main"); machdep();
   AFNI_logger("3dLocalHistog",argc,argv);
   if( getpid()%2 ) AUTHOR("Bilbo Baggins"); else AUTHOR("Thorin Oakenshield");
   AFNI_SETUP_OMP(0) ;  /* 24 Jun 2013 */

   /*---- loop over options ----*/

   while( iarg < argc && argv[iarg][0] == '-' ){

     if( strcmp(argv[iarg],"-help") == 0 || strcmp(argv[iarg],"-h") == 0){
        usage_3dLocalHistog(strlen(argv[iarg])>3 ? 2:1);
        exit(0);
     }

     if( strncmp(argv[iarg],"-qu",3) == 0 ){
       verb = 0 ; iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-verb",5) == 0 ){
       verb++ ; iarg++ ; continue ;
     }

#ifdef ALLOW_PROB
     if( strncmp(argv[iarg],"-prob",5) == 0 ){
       do_prob = 1 ; iarg++ ; continue ;
     }
#endif

     if( strcmp(argv[iarg],"-exclude") == 0 ){
       int ebot=-6666666,etop=-6666666 , ee ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-exclude'") ;
       sscanf(argv[iarg],"%d..%d",&ebot,&etop) ;
       if( ebot >= -TWO15 && ebot <= TWO15 ){
         if( etop < -TWO15 || etop > TWO15 || etop < ebot ) etop = ebot ;
         exlist = (int *)realloc(exlist,sizeof(int)*(etop-ebot+1+numex+1)) ;
         for( ee=ebot ; ee <= etop ; ee++ ){ if( ee != 0 ) exlist[numex++] = ee ; }
       }
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-excNONLAB") == 0 ){
       do_excNONLAB = 1 ; iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-prefix") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-prefix'") ;
       prefix = strdup(argv[iarg]) ;
       if( !THD_filename_ok(prefix) ) ERROR_exit("Bad -prefix!") ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-hsave") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-hsave'") ;
       ohist_name = strdup(argv[iarg]) ;
       if( !THD_filename_ok(ohist_name) ) ERROR_exit("Bad -hsave!") ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-mincount") == 0 ){
       char *cpt ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-mincount'") ;
       mincount = (float)strtod(argv[iarg],&cpt) ;
#if 0
       if( mincount > 0.0f && mincount < 50.0f && *cpt == '%' )  /* percentage */
         mincount = -0.01f*mincount ;
#endif
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-nbhd") == 0 ){
       char *cpt ;
       if( ntype  >  0    ) ERROR_exit("Can't have 2 '-nbhd' options") ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-nbhd'") ;

       cpt = argv[iarg] ;
       if( strncasecmp(cpt,"SPHERE",6) == 0 ){
         sscanf( cpt+7 , "%f" , &na ) ;
         ntype = NTYPE_SPHERE ;
       } else if( strncasecmp(cpt,"RECT",4) == 0 ){
         sscanf( cpt+5 , "%f,%f,%f" , &na,&nb,&nc ) ;
         if( na == 0.0f && nb == 0.0f && nc == 0.0f )
           ERROR_exit("'RECT(0,0,0)' is not a legal neighborhood") ;
         ntype = NTYPE_RECT ;
       } else if( strncasecmp(cpt,"RHDD",4) == 0 ){
         sscanf( cpt+5 , "%f" , &na ) ;
         if( na == 0.0f ) ERROR_exit("Can't have a RHDD of radius 0") ;
         ntype = NTYPE_RHDD ;
       } else if( strncasecmp(cpt,"TOHD",4) == 0 ){
         sscanf( cpt+5 , "%f" , &na ) ;
         if( na == 0.0f ) ERROR_exit("Can't have a TOHD of radius 0") ;
         ntype = NTYPE_TOHD ;
       } else {
         ERROR_exit("Unknown -nbhd shape: '%s'",cpt) ;
       }
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-lab_file") == 0 || strcmp(argv[iarg],"-labfile") == 0 ){
       char **labnum ; int nbad=0 ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ;
       if( labfile != NULL ) ERROR_exit("Can't use '%s' twice!",argv[iarg-1]) ;
       labfile = strdup(argv[iarg]) ;
       labnel = THD_string_table_read(labfile,0) ;
       if( labnel == NULL || labnel->vec_num < 2 )
         ERROR_exit("Can't read label file '%s'",labfile) ;
       nlab   = labnel->vec_len ;
       labnum = (char **)labnel->vec[0] ;
       lablab = (char **)labnel->vec[1] ;
       labval = (int *)calloc(sizeof(int),nlab) ;
       for( ii=0 ; ii < nlab ; ii++ ){
         if( labnum[ii] != NULL ){
           labval[ii] = (int)strtod(labnum[ii],NULL) ;
           if( labval[ii] < -TWO15 || labval[ii] > TWO15 ){ labval[ii] = 0; nbad++; }
         }
       }
       if( nbad > 0 )
         ERROR_message("%d label values are outside the range %d..%d :-(" ,
         nbad , -TWO15 , TWO15 ) ;
       iarg++ ; continue ;
     }

     ERROR_message("** 3dLocalHistog: Illegal option: '%s'",argv[iarg]) ;
     suggest_best_prog_option(argv[0], argv[iarg]);
     exit(1) ;

   } /*--- end of loop over options ---*/

   /*---- check for stupid user inputs ----*/

   if( iarg >= argc ) ERROR_exit("No datasets on command line?") ;

   if( ohist_name == NULL && strcmp(prefix,"NULL") == 0 )
     ERROR_exit("-prefix NULL is only meaningful if you also use -hsave :-(") ;

   /*------------ scan input datasets, built overall histogram ------------*/

   nsar  = argc - iarg ;
   insar = (THD_3dim_dataset **)malloc(sizeof(THD_3dim_dataset *)*nsar) ;

   if( verb ) fprintf(stderr,"Scanning %d datasets ",nsar) ;

   ohist = (UINT32 *)calloc(sizeof(UINT32),TWO16) ;

   for( ids=iarg ; ids < argc ; ids++ ){                      /* dataset loop */
     insar[ids-iarg] = inset = THD_open_dataset(argv[ids]) ;
     CHECK_OPEN_ERROR(inset,argv[ids]) ;
     if( ids == iarg ){
       nx = DSET_NX(inset); ny = DSET_NY(inset); nz = DSET_NZ(inset); nvox = nx*ny*nz;
     } else if( nx != DSET_NX(inset) ||
                ny != DSET_NY(inset) || nz != DSET_NZ(inset) ){
       ERROR_exit("Dataset %s grid doesn't match!",argv[ids]) ;
     }
     if( !THD_datum_constant(inset->dblk) )
       ERROR_exit("Dataset %s doesn't have a fixed data type! :-(",argv[ids]) ;
     if( THD_need_brick_factor(inset) )
       ERROR_exit("Dataset %s has scale factors! :-(",argv[ids]) ;
     if( DSET_BRICK_TYPE(inset,0) != MRI_byte  &&
         DSET_BRICK_TYPE(inset,0) != MRI_short &&
         DSET_BRICK_TYPE(inset,0) != MRI_float    )
       ERROR_exit("Dataset %s is not byte- or short-valued! :-(",argv[ids]) ;
     DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ;

     for( ii=0 ; ii < DSET_NVALS(inset) ; ii++ ){ /* add to overall histogram */
       if( verb ) fprintf(stderr,".") ;
       switch( DSET_BRICK_TYPE(inset,ii) ){
         case MRI_short:{
           short *sar = (short *)DSET_BRICK_ARRAY(inset,ii) ;
           for( kk=0 ; kk < nvox ; kk++ ) ohist[ sar[kk]+TWO15 ]++ ;
         }
         break ;
         case MRI_byte:{
           byte *bar = (byte *)DSET_BRICK_ARRAY(inset,ii) ;
           for( kk=0 ; kk < nvox ; kk++ ) ohist[ bar[kk]+TWO15 ]++ ;
         }
         break ;
         case MRI_float:{
           float *far = (float *)DSET_BRICK_ARRAY(inset,ii) ; short ss ;
           for( kk=0 ; kk < nvox ; kk++ ){ ss = SHORTIZE(far[kk]); ohist[ss+TWO15]++; }
         }
         break ;
       }
     } /* end of sub-brick loop */

     DSET_unload(inset) ;  /* will re-load later, as needed */

   } /* end of dataset loop */

   if( verb ) fprintf(stderr,"\n") ;

   /*-------------- process overall histogram for fun and profit -------------*/

   /* if we didn't actually find 0, put it in the histogram now */

   if( ohist[0+TWO15] == 0 ){ ohist[0+TWO15] = 1 ; ohzadd = 1 ; }

   /* excNONLAB? */

   if( nlab > 0 && do_excNONLAB ){
     byte *klist = (byte *)calloc(sizeof(byte),TWO16) ; int nee ;
     for(     ii=0 ; ii < nlab  ; ii++ ){ if( labval[ii] != 0 ) klist[labval[ii]+TWO15] = 1 ; }
     for( nee=ii=0 ; ii < TWO16 ; ii++ ){ if( !klist[ii] ) nee++ ; }
     exlist = (int *)realloc(exlist,sizeof(int)*(numex+nee+1)) ;
     for(     ii=0 ; ii < TWO16 ; ii++ ){ if( ii != TWO15 && !klist[ii] ) exlist[numex++] = ii-TWO15 ; }
     free(klist) ;
   }

   /* make a copy of ohist and edit it for mincount, etc */

   mhist = (UINT32 *)malloc(sizeof(UINT32)*TWO16) ;
   memcpy(mhist,ohist,sizeof(UINT32)*TWO16) ;
   mcc = (mincount < 0.0f) ? (int)(-mincount*nvox) : (int)mincount ;
   if( mcc > 1 ){
     for( ids=ii=0 ; ii < TWO16 ; ii++ ){
       if( ii != TWO15 && mhist[ii] > 0 && mhist[ii] < mcc ){ mhist[ii] = 0; ids++; }
     }
     if( ids > 0 && verb )
       INFO_message("Edited out %d values with overall histogram counts less than %d",ids,mcc) ;
   }
   if( numex > 0 ){
     int ee ;
     for( ids=0,ii=0 ; ii < numex ; ii++ ){
       ee = exlist[ii] ;
       if( mhist[ee+TWO15] > 0 ){ mhist[ee+TWO15] = 0; ids++; }
     }
     free(exlist) ;
     if( ids > 0 && verb )
       INFO_message("Edited out %d values from the exclude list",ids) ;
   }

   /* count number of values with nonzero (edited) counts */

   numval = 0 ;
   for( ii=0 ; ii < TWO16 ; ii++ ) if( mhist[ii] != 0 ) numval++ ;

   if( numval == 0 ) ERROR_exit("Nothing found! WTF?") ;  /* should not happen */

   /* make list of all values with nonzero (edited) count */

   rlist = (int *)malloc(sizeof(int)*numval) ;
   if( verb > 1 ) fprintf(stderr,"++ Include list:") ;
   for( ii=kk=0 ; ii < TWO16 ; ii++ ){
     if( mhist[ii] != 0 ){
       rlist[kk++] = ii-TWO15 ;
       if( verb > 1 ) fprintf(stderr," %d[%u]",ii-TWO15,mhist[ii]) ;
     }
   }
   if( verb > 1 ) fprintf(stderr,"\n") ;

   rbot = rlist[0] ; rtop = rlist[numval-1] ; /* smallest and largest values found */

   if( rbot == rtop ) ERROR_exit("Only one value (%d) found in all inputs!",rbot) ;

   /* if 0 isn't first in rlist, then
      put it in first place and move negative values up by one spot */

   if( rbot < 0 ){
     for( kk=0 ; kk < numval && rlist[kk] != 0 ; kk++ ) ; /*nada*/
     if( kk < numval ){   /* should always be true */
       for( ii=kk-1 ; ii >= 0 ; ii-- ) rlist[ii+1] = rlist[ii] ;
       rlist[0] = 0 ;
     }
   }

   if( verb )
     INFO_message("Value range = %d..%d (%d distinct values)",rbot,rtop,numval );

   /* save overall histogram? */

   if( ohist_name != NULL ){
     FILE *fp = fopen(ohist_name,"w") ; int nl=0 ;
     if( fp == NULL ) ERROR_exit("Can't open -hsave '%s' for output!",ohist_name) ;
     if( ohzadd ) ohist[0+TWO15] = 0 ;
     for( ii=0 ; ii < TWO16 ; ii++ ){
       if( ohist[ii] != 0 ){ fprintf(fp,"%6d %u\n",ii-TWO15,ohist[ii]); nl++; }
     }
     fclose(fp) ;
     if( verb ) INFO_message("Wrote %d lines to -hsave file %s",nl,ohist_name) ;
   }

   free(ohist) ; free(mhist) ; mhist = ohist = NULL ;  /* done with this */

   if( strcmp(prefix,"NULL") == 0 ) exit(0) ;   /* special case */

   /*----------- build the neighborhood mask -----------*/

   if( ntype <= 0 ){         /* default neighborhood */
     ntype = NTYPE_SPHERE ; na = 0.0f ;
     if( verb ) INFO_message("Using default neighborhood = self") ;
   }

   switch( ntype ){
     default:
       ERROR_exit("WTF?  ntype=%d",ntype) ;  /* should not happen */

     case NTYPE_SPHERE:{
       float dx , dy , dz ;
       if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; }
       else           { dx = fabsf(DSET_DX(insar[0])) ;
                        dy = fabsf(DSET_DY(insar[0])) ;
                        dz = fabsf(DSET_DZ(insar[0])) ; }
       nbhd = MCW_spheremask( dx,dy,dz , na ) ;
     }
     break ;

     case NTYPE_RECT:{
       float dx , dy , dz ;
       if( na < 0.0f ){ dx = 1.0f; na = -na; } else dx = fabsf(DSET_DX(insar[0]));
       if( nb < 0.0f ){ dy = 1.0f; nb = -nb; } else dy = fabsf(DSET_DY(insar[0]));
       if( nc < 0.0f ){ dz = 1.0f; nc = -nc; } else dz = fabsf(DSET_DZ(insar[0]));
       nbhd = MCW_rectmask( dx,dy,dz , na,nb,nc ) ;
     }
     break ;

     case NTYPE_RHDD:{
       float dx , dy , dz ;
       if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; }
       else           { dx = fabsf(DSET_DX(insar[0])) ;
                        dy = fabsf(DSET_DY(insar[0])) ;
                        dz = fabsf(DSET_DZ(insar[0])) ; }
       nbhd = MCW_rhddmask( dx,dy,dz , na ) ;
     }
     break ;

     case NTYPE_TOHD:{
       float dx , dy , dz ;
       if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; }
       else           { dx = fabsf(DSET_DX(insar[0])) ;
                        dy = fabsf(DSET_DY(insar[0])) ;
                        dz = fabsf(DSET_DZ(insar[0])) ; }
       nbhd = MCW_tohdmask( dx,dy,dz , na ) ;
     }
     break ;
   }

   if( verb ) INFO_message("Neighborhood comprises %d voxels",nbhd->num_pt) ;

   /*------- actually do some work for a change (is it lunchtime yet?) -------*/

   if( verb ) fprintf(stderr,"Voxel-wise histograms ") ;

   outset = THD_localhistog( nsar,insar , numval,rlist , nbhd , do_prob,verb ) ;

   if( outset == NULL ) ERROR_exit("Function THD_localhistog() fails?!") ;

   /*---- save resulting dataset ----*/

   EDIT_dset_items( outset , ADN_prefix,prefix , ADN_none ) ;

   tross_Copy_History( insar[0] , outset ) ;
   tross_Make_History( "3dLocalHistog" , argc,argv , outset ) ;

   /* but first attach labels to sub-bricks */

   EDIT_BRICK_LABEL(outset,0,"0:Other") ;
   for( kk=1 ; kk < numval ; kk++ ){
     sprintf(buf,"%d:",rlist[kk]) ;
     for( ii=0 ; ii < nlab ; ii++ ){
       if( labval[ii] == rlist[kk] && lablab[ii] != NULL ){
         ids = strlen(buf) ;
         MCW_strncpy(buf+ids,lablab[ii],THD_MAX_SBLABEL-ids) ;
         break ;
       }
     }
     EDIT_BRICK_LABEL(outset,kk,buf) ;
   }

   DSET_write( outset ) ;
   if( verb ) WROTE_DSET( outset ) ;
   exit(0) ;
}
THD_3dim_dataset * THD_localhistog( int nsar , THD_3dim_dataset **insar ,
                                    int numval , int *rlist , MCW_cluster *nbhd ,
                                    int do_prob , int verb )
{
   THD_3dim_dataset *outset=NULL , *inset ;
   int nvox=DSET_NVOX(insar[0]) ;
   int ids, iv, bb, nnpt=nbhd->num_pt ;
   MRI_IMAGE *bbim ; int btyp ;
   float **outar , **listar ;

ENTRY("THD_localhistog") ;

   /*---- create output dataset ----*/

   outset = EDIT_empty_copy(insar[0]) ;
   EDIT_dset_items( outset ,
                      ADN_nvals     , numval    ,
                      ADN_datum_all , MRI_float ,
                      ADN_nsl       , 0         ,
                      ADN_brick_fac , NULL      ,
                    ADN_none ) ;
   outar = (float **)malloc(sizeof(float *)*numval) ;
   for( bb=0 ; bb < numval ; bb++ ){
     EDIT_substitute_brick( outset , bb , MRI_float , NULL ) ;
     outar[bb] = DSET_BRICK_ARRAY(outset,bb) ;
   }

   /*---- make mapping between values and arrays to get those values ----*/

   listar = (float **)malloc(sizeof(float *)*TWO16) ;
   for( bb=0 ; bb < TWO16 ; bb++ ) listar[bb] = outar[0] ;
   for( bb=1 ; bb < numval ; bb++ ){
     listar[ rlist[bb] + TWO15 ] = outar[bb] ;
   }

   /*----------- loop over datasets, add in counts for all voxels -----------*/

   for( ids=0 ; ids < nsar ; ids++ ){              /* dataset loop */
     inset = insar[ids] ; DSET_load(inset) ;
     for( iv=0 ; iv < DSET_NVALS(inset) ; iv++ ){  /* sub-brick loop */
       if( verb ) fprintf(stderr,".") ;
       bbim = DSET_BRICK(inset,iv) ; btyp = bbim->kind ;
       if( nnpt == 1 ){                            /* only 1 voxel in nbhd */
         int qq,ii,jj,kk,ib,nb ;
         switch( bbim->kind ){
           case MRI_short:{
             short *sar = MRI_SHORT_PTR(bbim) ;
             for( qq=0 ; qq < nvox ; qq++ ) listar[sar[qq]+TWO15][qq]++ ;
           }
           break ;
           case MRI_byte:{
             byte *bar = MRI_BYTE_PTR(bbim) ;
             for( qq=0 ; qq < nvox ; qq++ ) listar[bar[qq]+TWO15][qq]++ ;
           }
           break ;
           case MRI_float:{
             float *far = MRI_FLOAT_PTR(bbim) ; short ss ;
             for( qq=0 ; qq < nvox ; qq++ ){ ss = SHORTIZE(far[qq]); listar[ss+TWO15][qq]++; }
           }
           break ;
         }
       } else {                                    /* multiple voxels in nbhd */
 AFNI_OMP_START ;
#pragma omp parallel
 { int qq,ii,jj,kk,ib,nb ; void *nar ; short *sar,ss ; byte *bar ; float *far ;
   nar = malloc(sizeof(float)*nnpt) ;
   sar = (short *)nar ; bar = (byte *)nar ; far = (float *)nar ;
#pragma omp for
         for( qq=0 ; qq < nvox ; qq++ ){           /* qq=voxel index */
           ii = DSET_index_to_ix(inset,qq) ;
           jj = DSET_index_to_jy(inset,qq) ;
           kk = DSET_index_to_kz(inset,qq) ;
           nb = mri_get_nbhd_array( bbim , NULL , ii,jj,kk , nbhd , nar ) ;
           if( nb == 0 ) continue ;
           switch( btyp ){
             case MRI_short:
               for( ib=0 ; ib < nb ; ib++ ) listar[sar[ib]+TWO15][qq]++ ;
             break ;
             case MRI_byte:
               for( ib=0 ; ib < nb ; ib++ ) listar[bar[ib]+TWO15][qq]++ ;
             break ;
             case MRI_float:
               for( ib=0 ; ib < nb ; ib++ ){ ss = SHORTIZE(far[ib]); listar[ss+TWO15][qq]++; }
             break ;
           }
         } /* end of voxel loop */
   free(nar) ;
 } /* end of OpenMP */
 AFNI_OMP_END ;
       }
     } /* end of sub-brick loop */
     DSET_unload(inset) ;
   } /* end of dataset loop */

   if( verb ) fprintf(stderr,"\n") ;

   free(listar) ;

   /*---- post-process output ---*/

   if( do_prob ){
     byte **bbar ; int pp ;
 
     if( verb ) INFO_message("Conversion to probabilities") ;

 AFNI_OMP_START ;
#pragma omp parallel
 { int qq , ib ; float pfac , val ; byte **bbar ;
#pragma omp for
     for( qq=0 ; qq < nvox ; qq++ ){
       pfac = 0.0001f ;
       for( ib=0 ; ib < numval ; ib++ ) pfac += outar[ib][qq] ;
       pfac = 250.0f / pfac ;
       for( ib=0 ; ib < numval ; ib++ ){
         val = outar[ib][qq]*pfac ; outar[ib][qq] = BYTEIZE(val) ;
       }
     }
 } /* end OpenMP */
 AFNI_OMP_END ;

     bbar = (byte **)malloc(sizeof(byte *)*numval) ;
     for( bb=0 ; bb < numval ; bb++ ){
       bbar[bb] = (byte *)malloc(sizeof(byte)*nvox) ;
       for( pp=0 ; pp < nvox ; pp++ ) bbar[bb][pp] = (byte)outar[bb][pp] ;
       EDIT_substitute_brick(outset,bb,MRI_byte,bbar[bb]) ;
       EDIT_BRICK_FACTOR(outset,bb,0.004f) ;
     }
     free(bbar) ;

   } /* end of do_prob */

   free(outar) ;
   RETURN(outset) ;
}
int main( int argc , char *argv[] )
{
   MRI_IMAGE *imin, *imout , *imout_orig;
   THD_3dim_dataset *iset, *oset , *ooset;
   char *prefix = "SpatNorm", *bottom_cuts = NULL;
   int iarg , verb=0, OrigSpace = 0 , specie = HUMAN;
   float SpatNormDxyz= 0.0, iset_scaled=1.0;
   THD_ivec3 orixyz , nxyz ;
   THD_fvec3 dxyz , orgxyz, originRAIfv, fv2;


   mainENTRY("3dSpatNorm main") ; machdep() ; 
   if (argc == 1) { usage_3dSpatNorm(1); exit(0); }

   /*--- options ---*/

   iarg = 1 ;
   OrigSpace = 0;
   while( iarg < argc && argv[iarg][0] == '-' ){
      if (strcmp(argv[iarg],"-h") == 0 || strcmp(argv[iarg],"-help") == 0 ) { 
         usage_3dSpatNorm(strlen(argv[iarg]) > 3 ? 2:1);
         exit(0); 
      }
      
     /* -prefix */

     if( strcmp(argv[iarg],"-prefix") == 0 ){
       if( ++iarg >= argc ){
         fprintf(stderr,"**ERROR: -prefix requires another argument!\n") ;
         exit(1) ;
       }
       prefix = strdup(argv[iarg]) ;
       if( !THD_filename_ok(prefix) ){
         fprintf(stderr,"**ERROR: -prefix value contains forbidden characters!\n") ;
         exit(1) ;
       }
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-dxyz") == 0 ){
       if( ++iarg >= argc ){
         fprintf(stderr,"**ERROR: -dxyz requires another argument!\n") ;
         exit(1) ;
       }
       SpatNormDxyz = atof(argv[iarg]) ;
       
       iarg++ ; continue ;
     }
     if( strcmp(argv[iarg],"-bottom_cuts") == 0 ){
       if( ++iarg >= argc ){
         fprintf(stderr,"**ERROR: -bottom_cuts requires another argument!\n") ;
         exit(1) ;
       }
       bottom_cuts = argv[iarg] ;
       
       iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-verb",5) == 0 ){
       verb++ ; iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-human",5) == 0 ){
       specie = HUMAN ; iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-monkey",5) == 0 ){
       specie = MONKEY ; iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-marmoset",5) == 0 ){
       specie = MARMOSET ; iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-rat",5) == 0 ){
       specie = RAT ; iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-orig_space",10) == 0 ){
       OrigSpace = 1 ; iarg++ ; continue ;
     }
     
     fprintf(stderr,"**ERROR: %s is unknown option!\n",argv[iarg]) ;
     suggest_best_prog_option(argv[0], argv[iarg]);
     exit(1) ;
   }

   if( iarg >= argc ){
     fprintf(stderr,"**ERROR: no input dataset name on command line?!\n") ;
     exit(1) ;
   }

   /*--- read dataset ---*/

   iset = THD_open_dataset( argv[iarg] ) ;
   if( !ISVALID_DSET(iset) ){
     fprintf(stderr,"**ERROR: can't open dataset %s\n",argv[iarg]) ;
     exit(1) ;
   }

   /*--- get median brick --*/

   if( verb ) fprintf(stderr,"++3dSpatNorm: loading dataset\n") ;

   if (specie == MARMOSET) {
      iset_scaled = 2.5;
      THD_volDXYZscale(iset->daxes, iset_scaled, 0);
      specie = MONKEY;
   }
   imin = THD_median_brick( iset ) ;
   if( imin == NULL ){
     fprintf(stderr,"**ERROR: can't load dataset %s\n",argv[iarg]) ;
     exit(1) ;
   }
   imin->dx = fabs(iset->daxes->xxdel) ;
   imin->dy = fabs(iset->daxes->yydel) ;
   imin->dz = fabs(iset->daxes->zzdel) ;
   
   
   mri_speciebusiness(specie);
   mri_brain_normalize_cuts(bottom_cuts);
   
   if (SpatNormDxyz) {
      if (verb) fprintf(stderr,"Overriding default resampling\n");
      mri_brainormalize_initialize(SpatNormDxyz, SpatNormDxyz, SpatNormDxyz);
   } else {
      float xxdel, yydel, zzdel, minres;
      if (specie == MONKEY) minres = 0.5;
      else if (specie == MARMOSET) minres = 0.2;
      else if (specie == RAT) minres = 0.1;
      else minres = 0.5;
      /* don't allow for too low a resolution, please */
      if (imin->dx < minres) xxdel = minres;
      else xxdel = imin->dx;
      if (imin->dy < minres) yydel = minres;
      else yydel = imin->dy;
      if (imin->dz < minres) zzdel = minres;
      else zzdel = imin->dz;
      if (verb) {
         fprintf(stderr,
                  "%s:\n"
                  " Original resolution %f, %f, %f\n"
                  " SpatNorm resolution %f, %f, %f\n",
                  "3dSpatnorm", imin->dx, imin->dy, imin->dz, 
                     xxdel, yydel, zzdel);
      }   
      mri_brainormalize_initialize(xxdel, yydel, zzdel);
   }
   
      /* To get around the #define for voxel counts and dimensions */
   mri_brainormalize_initialize(imin->dz, imin->dy, imin->dz); 
   
   /* me needs the origin of this dset in RAI world */
   LOAD_FVEC3( originRAIfv , 
               iset->daxes->xxorg , iset->daxes->yyorg , iset->daxes->zzorg) ;
   originRAIfv = THD_3dmm_to_dicomm( iset , originRAIfv ) ;

   LOAD_FVEC3(fv2, iset->daxes->xxorg + (iset->daxes->nxx-1)*iset->daxes->xxdel ,
                   iset->daxes->yyorg + (iset->daxes->nyy-1)*iset->daxes->yydel ,
                   iset->daxes->zzorg + (iset->daxes->nzz-1)*iset->daxes->zzdel);
   fv2 = THD_3dmm_to_dicomm( iset , fv2 ) ;

   if( originRAIfv.xyz[0] > fv2.xyz[0] ) { 
      float tf; tf = originRAIfv.xyz[0]; 
                originRAIfv.xyz[0] = fv2.xyz[0];  fv2.xyz[0] = tf; } 
   if( originRAIfv.xyz[1] > fv2.xyz[1] ) { 
      float tf; tf = originRAIfv.xyz[1]; 
                originRAIfv.xyz[1] = fv2.xyz[1]; fv2.xyz[1] = tf; }
   if( originRAIfv.xyz[2] > fv2.xyz[2] ) { 
      float tf; tf = originRAIfv.xyz[2]; 
                originRAIfv.xyz[2] = fv2.xyz[2]; fv2.xyz[2] = tf; }
   
   if (verb) {
      fprintf(stderr,"++3dSpatNorm (ZSS): RAI origin info: %f %f %f\n", 
                     originRAIfv.xyz[0], originRAIfv.xyz[1], originRAIfv.xyz[2]);
   }
   
   
   DSET_unload( iset ) ;  /* don't need this data no more */

   /*-- convert image to shorts, if appropriate --*/

   if( DSET_BRICK_TYPE(iset,0) == MRI_short ||
       DSET_BRICK_TYPE(iset,0) == MRI_byte    ){

     imout = mri_to_short(0.0,imin) ; /* ZSS Oct 2012: Let function set scaling*/
     mri_free(imin) ; imin = imout ;
   }

   /*--- normalize image spatially ---*/

   mri_brainormalize_verbose( verb ) ;
   if (OrigSpace) {
      imout = mri_brainormalize( imin , iset->daxes->xxorient,
                                     iset->daxes->yyorient,
                                     iset->daxes->zzorient , &imout_orig, NULL) ;
   } else {
      imout = mri_brainormalize( imin , iset->daxes->xxorient,
                                     iset->daxes->yyorient,
                                     iset->daxes->zzorient , NULL, NULL) ;
   }
   mri_free( imin ) ;

   if( imout == NULL ){
     fprintf(stderr,"**ERROR: normalization fails!?\n"); exit(1);
   }
   
   if (OrigSpace) {
      if( verb ) fprintf(stderr,"++3dSpatNorm: Output in Orignal space\n") ;
      mri_free( imout ) ;
      imout = imout_orig; 
      imout->xo = originRAIfv.xyz[0]; 
      imout->yo = originRAIfv.xyz[1]; 
      imout->zo = originRAIfv.xyz[2]; 
      imout_orig = NULL;
   } else {
      if( verb ) fprintf(stderr,"++3dSpatNorm: Output in SpatNorm space\n") ;
   }
   
#if 0
   if( AFNI_yesenv("WATERSHED") ){
     imin = mri_watershedize( imout , 0.10 ) ;
     if( imin != NULL ){ mri_free(imout); imout = imin; }
   }
#endif

   /*--- create output dataset ---*/
   if( verb )
     fprintf(stderr,"++3dSpatNorm: Creating output dset\n") ;

   oset = EDIT_empty_copy( NULL ) ;

   tross_Copy_History( iset , oset ) ;
   tross_Make_History( "3dSpatNorm" , argc,argv , oset ) ;

   LOAD_IVEC3( nxyz   , imout->nx    , imout->ny    , imout->nz    ) ;
   LOAD_FVEC3( dxyz   , imout->dx    , imout->dy    , imout->dz    ) ;
   LOAD_FVEC3( orgxyz , imout->xo    , imout->yo    , imout->zo    ) ;
   LOAD_IVEC3( orixyz , ORI_R2L_TYPE , ORI_A2P_TYPE , ORI_I2S_TYPE ) ;

   if( verb )
     fprintf(stderr,"++3dSpatNorm: EDIT_dset_items\n") ;
   EDIT_dset_items( oset ,
                      ADN_prefix      , prefix ,
                      ADN_datum_all   , imout->kind ,
                      ADN_nxyz        , nxyz ,
                      ADN_xyzdel      , dxyz ,
                      ADN_xyzorg      , orgxyz ,
                      ADN_xyzorient   , orixyz ,
                      ADN_malloc_type , DATABLOCK_MEM_MALLOC ,
                      ADN_view_type   , VIEW_ORIGINAL_TYPE ,
                      ADN_type        , HEAD_ANAT_TYPE ,
                      ADN_func_type   , ANAT_BUCK_TYPE ,
                    ADN_none ) ;

   if( verb )
     fprintf(stderr,"++3dSpatNorm: EDIT_substitute_brick\n") ;
   EDIT_substitute_brick( oset , 0 , imout->kind , mri_data_pointer(imout) ) ;

   if (OrigSpace) {
      if( verb )
         fprintf(stderr,"++3dSpatNorm: Changing orientation from RAI\n") ;
      ooset = r_new_resam_dset ( oset, iset, 0, 0, 0, NULL, MRI_NN, NULL, 1, 0);
      if (!ooset) {
         fprintf(stderr,"**ERROR: Failed to reslice!?\n"); exit(1);
      }
      /* put prefix back, r_new_resam_dset puts dummy prefix */
      EDIT_dset_items( ooset ,
                       ADN_prefix      , prefix,
                       ADN_none ) ;

      DSET_delete(oset); oset = ooset; ooset = NULL;
   }

   if (iset_scaled != 1.0f) 
      THD_volDXYZscale(oset->daxes,
                      1/iset_scaled, 0);

   DSET_write(oset) ;
   if( verb )
     fprintf(stderr,"++3dSpatNorm: wrote dataset %s\n",DSET_BRIKNAME(oset)) ;
   
   exit(0) ;
}
Exemple #19
0
/*! Replace a voxel's value by the value's rank in the entire set of input datasets */
int main( int argc , char * argv[] )
{
   THD_3dim_dataset ** dsets_in = NULL, *dset=NULL; /*input and output datasets*/
   int nopt=0, nbriks=0, nsubbriks=0, ib=0, isb=0;
   byte *cmask=NULL;
   int *all_uniques=NULL, **uniques=NULL, *final_unq=NULL, *N_uniques=NULL;
   int N_final_unq=0, iun=0, total_unq=0;
   INT_HASH_DATUM *rmap=NULL, *hd=NULL;
   int imax=0, iunq=0, ii=0, id = 0;
   long int off=0;
   char *prefix=NULL;
   char stmp[THD_MAX_PREFIX+1]={""}; 
   FILE *fout=NULL;

   /*----- Read command line -----*/
   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
      Rank_help ();
      exit(0) ;
   }

   mainENTRY("3dRank main"); machdep(); AFNI_logger("3dRank",argc,argv);
   nopt = 1 ;
   
   while( nopt < argc && argv[nopt][0] == '-' ){
      if( strcmp(argv[nopt],"-ver") == 0 ){
         PRINT_VERSION("3dRank"); AUTHOR("Ziad Saad");
         nopt++; continue;
      }

      if( strcmp(argv[nopt],"-help") == 0 ){
         Rank_help();
         exit(0) ;
      }

      if( strcmp(argv[nopt],"-prefix") == 0 ){
         ++nopt;
         if (nopt>=argc) {
            fprintf(stderr,"**ERROR: Need string after -prefix\n");
            exit(1);
         }
         prefix = argv[nopt] ;
         ++nopt; continue;
      }
      if( strcmp(argv[nopt],"-input") == 0 ){
         dsets_in = (THD_3dim_dataset**)
                        calloc(argc-nopt+1, sizeof(THD_3dim_dataset*));
         ++nopt; nbriks=0;
         while (nopt < argc ) {
            dsets_in[nbriks] = THD_open_dataset( argv[nopt] );
            if( !ISVALID_DSET(dsets_in[nbriks]) ){
              fprintf(stderr,"**ERROR: can't open dataset %s\n",argv[nopt]) ;
              exit(1);
            }
            ++nopt; ++nbriks; 
         }
         continue;
      }
      
      ERROR_exit( " Error - unknown option %s", argv[nopt]);
   } 
   if (nopt < argc) {
      ERROR_exit( " Error unexplained trailing option: %s\n", argv[nopt]);
   }
   if (!nbriks) {
      ERROR_exit( " Error no volumes entered on command line?");
   }
   
   /* some checks and inits*/
   nsubbriks = 0;
   for (ib = 0; ib<nbriks; ++ib) {
      if (!is_integral_dset(dsets_in[ib], 0)) {
         ERROR_exit("Dset %s is not of an integral data type.", 
                        DSET_PREFIX(dsets_in[ib]));
      }
      nsubbriks += DSET_NVALS(dsets_in[ib]);
   }
   
   /* Now get unique arrays */
   uniques = (int **)calloc(nsubbriks, sizeof(int*));
   N_uniques = (int *)calloc(nsubbriks, sizeof(int));
   total_unq = 0;
   iun = 0;
   for (ib = 0; ib<nbriks; ++ib) {
      DSET_mallocize(dsets_in[ib]); DSET_load(dsets_in[ib]);
      for (isb=0; isb<DSET_NVALS(dsets_in[ib]); ++isb) {
         uniques[iun] = THD_unique_vals(dsets_in[ib], isb,
                                        &(N_uniques[iun]), cmask);
         total_unq += N_uniques[iun]; 
         ++iun;
      }
   }
   
   /* put all the arrays together and get the unique of the uniques */
   all_uniques = (int *)calloc(total_unq, sizeof(int));
   off=0;
   for (iun=0; iun<nsubbriks; ++iun) {
      memcpy(all_uniques+off, uniques[iun], N_uniques[iun]*sizeof(int));
      off += N_uniques[iun];
   }
   
   /* free intermediate unique arrays */
   for (iun=0; iun<nsubbriks; ++iun) {
      free(uniques[iun]);
   }
   free(uniques); uniques=NULL;
   free(N_uniques); N_uniques=NULL;
   
   /* get unique of catenated array */
   if (!(final_unq = UniqueInt (all_uniques, total_unq, &N_final_unq, 0 ))) {
      ERROR_exit( " Failed to get unique list (%d, %d, %d) ", 
                  total_unq, N_final_unq, nsubbriks);
   }
   free(all_uniques); all_uniques=NULL;
  
   if (prefix) {
      snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, 
               "%s.rankmap.1D", prefix);
   } else {
      if (nbriks == 1) {
        snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, 
                  "%s.rankmap.1D", DSET_PREFIX(dsets_in[0]));
      } else { 
         snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, 
                  "%s+.rankmap.1D", DSET_PREFIX(dsets_in[0]));
      }
   }
      
   if (stmp[0]) {
      if ((fout = fopen(stmp,"w"))) {
         fprintf(fout, "#Rank Map (%d unique values)\n", N_final_unq);
         fprintf(fout, "#Col. 0: Rank\n");
         fprintf(fout, "#Col. 1: Input Dset Value\n");
      }
   } 

   
   /* get the maximum integer in the unique array */
   imax = 0;
   for (iunq=0; iunq<N_final_unq; ++iunq) {
      if (final_unq[iunq] > imax) imax = final_unq[iunq]; 
      if (fout) fprintf(fout, "%d   %d\n", iunq, final_unq[iunq]);
      hd = (INT_HASH_DATUM*)calloc(1,sizeof(INT_HASH_DATUM));
      hd->id = final_unq[iunq];
      hd->index = iunq;
      HASH_ADD_INT(rmap, id, hd); 
   }
   
   fclose(fout); fout=NULL;

   /* now cycle over all dsets and replace their voxel values with rank */
   for (ib = 0; ib<nbriks; ++ib) {
      for (isb=0; isb<DSET_NVALS(dsets_in[ib]); ++isb) {
         EDIT_BRICK_LABEL(  dsets_in[ib],isb, "rank" ) ;
         EDIT_BRICK_TO_NOSTAT(  dsets_in[ib],isb ) ;
         EDIT_BRICK_FACTOR( dsets_in[ib],isb, 0.0);/* no factors for rank*/
         switch (DSET_BRICK_TYPE(dsets_in[ib],isb) ){
            default:
               fprintf(stderr,
                        "** Bad dset type for unique operation.\n"
                        "Only Byte, Short, and float dsets are allowed.\n");
               break ; /* this should not happen here, 
                        so don't bother returning*/
            case MRI_short:{
               short *mar = (short *) DSET_ARRAY(dsets_in[ib],isb) ;
               if (imax >  MRI_TYPE_maxval[MRI_short]) {
                  WARNING_message("Maximum rank value of %d is\n"
                                  "than maximum value for dset datatype of %d\n",
                                  imax, MRI_TYPE_maxval[MRI_short]);
               }
               for( ii=0 ; ii < DSET_NVOX(dsets_in[ib]) ; ii++ )
                  if (!cmask || cmask[ii]) {
                     id = (int)mar[ii];
                     HASH_FIND_INT(rmap,&id ,hd);
                     if (hd) mar[ii] = (short)(hd->index); 
                     else 
                       ERROR_exit("** Failed to find key %d in hash table\n",id);
                  } else mar[ii] = 0;
            }
            break ;
            case MRI_byte:{
               byte *mar ;
               if (imax >  MRI_TYPE_maxval[MRI_short]) {
                  WARNING_message("Maximum rank value of %d is\n"
                                  "than maximum value for dset datatype of %d\n",
                                  imax, MRI_TYPE_maxval[MRI_byte]);
               }
               mar = (byte *) DSET_ARRAY(dsets_in[ib],isb) ;
               for( ii=0 ; ii < DSET_NVOX(dsets_in[ib]) ; ii++ )
                  if (!cmask || cmask[ii]) {
                     id = (int)mar[ii];
                     HASH_FIND_INT(rmap,&id ,hd);
                     if (hd) mar[ii] = (byte)(hd->index); 
                     else 
                       ERROR_exit("** Failed to find key %d in hash table\n",id);
                  } else mar[ii] = 0;
            }
            break ;
            case MRI_float:{
               float *mar = (float *) DSET_ARRAY(dsets_in[ib],isb) ;
               for( ii=0 ; ii < DSET_NVOX(dsets_in[ib]) ; ii++ )
                  if (!cmask || cmask[ii]) {
                     id = (int)mar[ii]; /* Assuming float is integral valued */
                     HASH_FIND_INT(rmap,&id ,hd);
                     if (hd) mar[ii] = (float)(hd->index); 
                     else 
                       ERROR_exit("** Failed to find key %d in hash table\n",id);
                  } else mar[ii] = 0;
            }
            break ;

         }
      }

      /* update range, etc. */
      THD_load_statistics(dsets_in[ib]);
      
      /* Now write the bricks */
      if (prefix) {
         if (nbriks == 1) { 
            snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, 
                     "%s", prefix);
         } else {
            snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, 
                     "r%02d.%s", ib, prefix);
         }
      } else {
         snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, 
                  "rank.%s", DSET_PREFIX(dsets_in[ib]));
      }
      EDIT_dset_items( dsets_in[ib] ,
                       ADN_prefix   , stmp ,
                       ADN_none ) ;
      
      /* change storage mode, this way prefix will determine
         format of output dset */
      dsets_in[ib]->dblk->diskptr->storage_mode = STORAGE_BY_BRICK;
      
      tross_Make_History( "3dRank" , argc, argv , dsets_in[ib] ) ;
      if (DSET_IS_MASTERED(dsets_in[ib])) {
         /*  THD_write_3dim_dataset won't write a mastered dude */
         dset = EDIT_full_copy(dsets_in[ib],stmp); 
      } else {
         dset = dsets_in[ib];
      }
      
      /* New ID */
      ZERO_IDCODE(dset->idcode);
      dset->idcode = MCW_new_idcode() ;
      
      if (!THD_write_3dim_dataset( NULL, stmp, dset,True )) {
         ERROR_message("Failed to write %s", stmp);
         exit(1);  
      } else {
         WROTE_DSET(dsets_in[ib]); 
         if (dset != dsets_in[ib]) DSET_deletepp(dset);
         DSET_deletepp(dsets_in[ib]);
         
      }
   }
   
   /* destroy hash */
   while (rmap) {
      hd = rmap;
      HASH_DEL(rmap,hd);
      free(hd);
   }

   free(final_unq);  final_unq=NULL;
   
   exit(0);
}
Exemple #20
0
int main( int argc , char *argv[] )
{
   int vstep=0 , ii,nvox , ntin , ntout , do_one=0 , nup=-1 ;
   THD_3dim_dataset *inset=NULL , *outset ;
   char *prefix="Upsam", *dsetname=NULL ;
   int verb=0 , iarg=1, datum = MRI_float;
   float *ivec , *ovec , trin , trout, *fac=NULL, *ofac=NULL, 
         top=0.0, maxtop=0.0;

   /*------- help the pitifully ignorant user? -------*/

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
     printf(
      "Usage: 3dUpsample [options] n dataset\n"
      "\n"
      "* Upsamples a 3D+time dataset, in the time direction,\n"
      "   by a factor of 'n'.\n"
      "* The value of 'n' must be between 2 and 320 (inclusive).\n"
      "* The output dataset is in float format by default.\n"
      "\n"
      "Options:\n"
      "--------\n"
      " -1 or -one = Use linear interpolation. Otherwise,\n"
      " or -linear   7th order polynomial interpolation is used.\n"
      "\n"
      " -prefix pp = Define the prefix name of the output dataset.\n"
      "              [default prefix is 'Upsam']\n"
      "\n"
      " -verb      = Be eloquently and mellifluosly verbose.\n"
      "\n"
      " -n n       = An alternate way to specify n\n"
      " -input dataset = An alternate way to specify dataset\n"
      "\n"
      " -datum ddd = Use datatype ddd at output. Choose from\n"
      "              float (default), short, byte.\n"
      "Example:\n"
      "--------\n"
      " 3dUpsample -prefix LongFred 5 Fred+orig\n"
      "\n"
      "Nota Bene:\n"
      "----------\n"
      "* You should not use this for files that were 3dTcat-ed across\n"
      "   imaging run boundaries, since that will result in interpolating\n"
      "   between non-contiguous time samples!\n"
      "* If the input has M time points, the output will have n*M time\n"
      "   points.  The last n-1 of them will be past the end of the original\n"
      "   time series.\n"
      "* This program gobbles up memory and diskspace as a function of n.\n"
      "  You can reduce output file size with -datum option.\n"
      "\n"
      "--- RW Cox - April 2008\n"
     ) ;
     PRINT_COMPILE_DATE ; exit(0) ;
   }

   mainENTRY("3dUpsample"); machdep();
   PRINT_VERSION("3dUpsample"); AUTHOR("RWCox") ;
   AFNI_logger("3dUpsample",argc,argv);

   /*------- read command line args -------*/

   datum = MRI_float;
   iarg = 1 ;
   while( iarg < argc && argv[iarg][0] == '-' ){

     if( strncasecmp(argv[iarg],"-prefix",5) == 0 ){
       if( ++iarg >= argc )
         ERROR_exit("Need argument after '%s'",argv[iarg-1]);
       prefix = argv[iarg] ;
       if( !THD_filename_ok(prefix) )
         ERROR_exit("Illegal string after -prefix: '%s'",prefix) ;
       iarg++ ; continue ;
     }

     if( strncasecmp(argv[iarg],"-one",4) == 0 ||
         strcmp     (argv[iarg],"-1"    ) == 0 ||
         strncasecmp(argv[iarg],"-lin",4) == 0   ){
       do_one = 1 ; iarg++ ; continue ;
     }

     if( strncasecmp(argv[iarg],"-verb",3) == 0 ){
       verb = 1 ; iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-n") == 0 ){
      if( ++iarg >= argc )
         ERROR_exit("Need argument after '%s'",argv[iarg-1]);
      nup = (int)strtod(argv[iarg],NULL) ;
      if( nup < 2 || nup > 320 )
        ERROR_exit("3dUpsample rate '%d' is outside range 2..320",nup) ;
      iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-input") == 0 ){
      if( ++iarg >= argc )
         ERROR_exit("Need argument after '%s'",argv[iarg-1]);
      dsetname = argv[iarg];
      iarg++ ; continue ;
     }
     
     if( strcasecmp(argv[iarg],"-datum") == 0 ){
      if( ++iarg >= argc )
         ERROR_exit("Need argument after '%s'",argv[iarg-1]);
      
         if( strcmp(argv[iarg],"short") == 0 ){
            datum = MRI_short ;
         } else if( strcmp(argv[iarg],"float") == 0 ){
            datum = MRI_float ;
         } else if( strcmp(argv[iarg],"byte") == 0 ){
            datum = MRI_byte ;
         } else {
            ERROR_message("-datum of type '%s' not supported in 3dUpsample!\n",
                    argv[iarg] ) ;
            exit(1) ;
         }
         
      iarg++ ; continue ;
     }
     
     ERROR_message("Unknown argument on command line: '%s'",argv[iarg]) ;
     suggest_best_prog_option(argv[0], argv[iarg]);
     exit (1);
   }

   /*------- check options for completeness and consistency -----*/
   
   if (nup == -1) {
      if( iarg+1 >= argc )
        ERROR_exit("need 'n' and 'dataset' on command line!") ;

      nup = (int)strtod(argv[iarg++],NULL) ;
      if( nup < 2 || nup > 320 )
        ERROR_exit("3dUpsample rate '%d' is outside range 2..320",nup) ;
   } 
   if (!dsetname) {
      if( iarg >= argc )
        ERROR_exit("need 'dataset' on command line!") ;
      dsetname = argv[iarg];
   }
   
   inset = THD_open_dataset(dsetname) ;
   if( !ISVALID_DSET(inset) )
     ERROR_exit("3dUpsample can't open dataset '%s'", dsetname) ;
   ntin = DSET_NVALS(inset) ; trin = DSET_TR(inset) ;
   if( ntin < 2 )
     ERROR_exit("dataset '%s' has only 1 value per voxel?!",dsetname) ;

   nvox = DSET_NVOX(inset) ;

   if( verb ) INFO_message("loading input dataset into memory") ;

   DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ;


   /*------ create output dataset ------*/

   ntout = ntin * nup ; trout = trin / nup ;

   /* scaling factor for output */
   fac = NULL; maxtop = 0.0;
   if (MRI_IS_INT_TYPE(datum)) {
      fac = (float *)calloc(DSET_NVALS(inset), sizeof(float));
      ofac = (float *)calloc(ntout, sizeof(float));
      for (ii=0; ii<DSET_NVALS(inset); ++ii) {
         top = MCW_vol_amax( DSET_NVOX(inset),1,1 , 
                             DSET_BRICK_TYPE(inset,ii), 
                             DSET_BRICK_ARRAY(inset,ii) ) ;
         if (DSET_BRICK_FACTOR(inset, ii)) 
            top = top * DSET_BRICK_FACTOR(inset,ii);
         fac[ii] = (top > MRI_TYPE_maxval[datum]) ? 
                        top/MRI_TYPE_maxval[datum] : 0.0 ;
         if (top > maxtop) maxtop = top;
      }
      if (storage_mode_from_filename(prefix) != STORAGE_BY_BRICK) {
         fac[0] = (maxtop > MRI_TYPE_maxval[datum]) ? 
                        maxtop/MRI_TYPE_maxval[datum] : 0.0 ;
         for (ii=0; ii<ntout; ++ii) 
            ofac[ii] = fac[0];
         if (verb) INFO_message("Forcing global scaling, Max = %f, fac = %f\n", 
                        maxtop, fac[0]);
      } else {
         if (verb) INFO_message("Reusing scaling factors of input dset\n");
         upsample_1( nup, DSET_NVALS(inset), fac, ofac);
      }
   }
   free(fac); fac = NULL;
   outset = EDIT_empty_copy(inset) ;
   EDIT_dset_items( outset ,
                        ADN_nvals     , ntout          ,
                        ADN_ntt       , DSET_NUM_TIMES(inset) > 1 ? ntout : 0 ,
                        ADN_datum_all , datum      ,
                        ADN_brick_fac , ofac           ,
                        ADN_prefix    , prefix         ,
                      ADN_none ) ;
   tross_Copy_History( inset , outset ) ;
   tross_Make_History( "3dUpsample" , argc,argv , outset ) ;
   free(ofac); ofac = NULL;
   
   if( outset->taxis != NULL ){
     outset->taxis->ttdel /= nup ;
     outset->taxis->ttdur /= nup ;
     if( outset->taxis->toff_sl != NULL ){
       for( ii=0 ; ii < outset->taxis->nsl ; ii++ )
         outset->taxis->toff_sl[ii] /= nup ;
     }
   }

   for( ii=0 ; ii < ntout ; ii++ ){ /* create empty bricks to be filled below */
     EDIT_substitute_brick( outset , ii , datum , NULL ) ;
   }

   /*------- loop over voxels and process them one at a time ---------*/

   if( verb )
     INFO_message("Upsampling time series from %d to %d: %s interpolation",
                  ntin , ntout , (do_one) ? "linear" : "heptic" ) ;

   if( verb && nvox > 499 ) vstep = nvox / 50 ;
   if( vstep > 0 ) fprintf(stderr,"++ voxel loop: ") ;

   ivec = (float *)malloc(sizeof(float)*ntin) ;
   ovec = (float *)malloc(sizeof(float)*ntout) ;

   for( ii=0 ; ii < nvox ; ii++ ){

     if( vstep > 0 && ii%vstep==vstep-1 ) vstep_print() ;

     THD_extract_array( ii , inset , 0 , ivec ) ;

     if( do_one ) upsample_1( nup , ntin , ivec , ovec ) ;
     else         upsample_7( nup , ntin , ivec , ovec ) ;

     THD_insert_series( ii , outset , ntout , MRI_float , ovec , 
                        datum==MRI_float ? 1:0 ) ;
   } /* end of loop over voxels */

   if( vstep > 0 ) fprintf(stderr," Done!\n") ;

   /*----- clean up and go away -----*/

   DSET_write(outset) ;
   if( verb ) WROTE_DSET(outset) ;
   if( verb ) INFO_message("Total CPU time = %.1f s",COX_cpu_time()) ;
   exit(0);
}
Exemple #21
0
char * STAVG_main( PLUGIN_interface * plint )
{
   MCW_idcode * idc ;                          /* input dataset idcode */
   THD_3dim_dataset * old_dset , * new_dset ;  /* input and output datasets */
   char * new_prefix , * str , * str2;         /* strings from user */
   int   meth;                                 /* chosen computation method */
   int   new_datum ,                           /* control parameters */
         old_datum , ntime ;

   int   te, ne, tinc, kim, nia;
   int   numepochs, minlength, maxlength, lastindex, navgpts;
   int   nvox , perc , new_units, old_units ;
   int   ii, ibot,itop , kk, jj; 
   int   no1, user_maxlength, delta;
   int   *pEpochLength, *pTimeIndex;
   int   nx, ny, nz, npix;
   float *pNumAvg;
   float old_dtime;

   MRI_IMAGE * stimim;
   
   MRI_IMARR *avgimar;

   byte   ** bptr  = NULL ;  /* one of these will be the array of */
   short  ** sptr  = NULL ;  /* pointers to input dataset sub-bricks */
   float  ** fptr  = NULL ;  /* (depending on input datum type) */

   float   * fxar  = NULL ;  /* array loaded from input dataset */
   float   * stimar = NULL ;
   float  ** fout  = NULL ;  /* will be array of output floats */

   float   * tar   = NULL ;  /* will be array of taper coefficients */

   float   * nstimar;

   /*--------------------------------------------------------------------*/
   /*----- Check inputs from AFNI to see if they are reasonable-ish -----*/

   /*--------- go to first input line ---------*/

   PLUTO_next_option(plint) ;

   idc      = PLUTO_get_idcode(plint) ;   /* get dataset item */
   old_dset = PLUTO_find_dset(idc) ;      /* get ptr to dataset */
   if( old_dset == NULL )
      return "*************************\n"
             "Cannot find Input Dataset\n"
             "*************************"  ;

   ntime = DSET_NUM_TIMES(old_dset) ;
   if( ntime < 2 )
      return "*****************************\n"
             "Dataset has only 1 time point\n"
             "*****************************"  ;

   ii = DSET_NVALS_PER_TIME(old_dset) ;
   if( ii > 1 )
      return "************************************\n"
             "Dataset has > 1 value per time point\n"
             "************************************"  ;
   
   old_datum = DSET_BRICK_TYPE( old_dset , 0 ) ; /* get old dataset datum type */
   new_datum = old_datum;
   old_dtime = DSET_TIMESTEP(old_dset);
   old_units = DSET_TIMEUNITS(old_dset);
   
   nvox = old_dset->daxes->nxx * old_dset->daxes->nyy * old_dset->daxes->nzz;
   npix = old_dset->daxes->nxx * old_dset->daxes->nyy;
   nx = old_dset->daxes->nxx;


   new_prefix = PLUTO_get_string(plint) ;   /* get string item (the output prefix) */
   if( ! PLUTO_prefix_ok(new_prefix) )      /* check if it is OK */
      return "************************\n"
             "Output Prefix is illegal\n"
             "************************"  ;

   /*--------- go to next input line ---------*/

   PLUTO_next_option(plint);

   stimim = PLUTO_get_timeseries(plint);
   if( stimim == NULL ) return "Please specify stimulus timing";

   if( stimim->nx < ntime ){
      return "**************************************\n"
             "Not enough pts in stimulus time-series\n"
             "**************************************";
   }

   stimar = MRI_FLOAT_PTR(stimim);


   delta = PLUTO_get_number(plint);

   if( abs(delta) > ntime ){
      return "************************\n"
             "Delta shift is too large\n"
             "************************";
   }
  
   /*initialize variables if not user specified */
   user_maxlength = ntime;
   no1 = 0;

   /*--------- go to next input line ---------*/

   PLUTO_next_option(plint);

   str  = PLUTO_get_string(plint) ;      /* get string item (the method) */
   meth = PLUTO_string_index( str ,      /* find it in list it is from */
                              _STAVG_NUM_METHODS ,
                              method_strings ) ;

   /*--------- see if the 4th option line is present --------*/

   str = PLUTO_get_optiontag( plint ) ;
   if( str != NULL ){
      user_maxlength = (int) PLUTO_get_number(plint) ;
      str2  = PLUTO_get_string(plint) ;      /* get string item (the method) */
      no1   = PLUTO_string_index( str2 ,      /* find it in list it is from */
                                 2 ,
                                 yes_no_strings) ;
   }
   

   /*------------------------------------------------------*/
   /*---------- At this point, the inputs are OK ----------*/

   PLUTO_popup_meter( plint ) ;  /* popup a progress meter */

   /*________________[ Main Code ]_________________________*/
  
   fout = avg_epochs( old_dset, stimar, user_maxlength, 1, meth, plint );
   if( fout == NULL ) return " \nError in avg_epochs() function!\n " ;
   
   if( RMB_DEBUG ) fprintf(stderr, "Done with avg_epochs\n");
   maxlength = M_maxlength;
   
   
   /*______________________________________________________*/

   
   new_dset = EDIT_empty_copy( old_dset ) ; /* start with copy of old one */

   { char * his = PLUTO_commandstring(plint) ;
     tross_Copy_History( old_dset , new_dset ) ;
     tross_Append_History( new_dset , his ) ; free( his ) ;
   }
   
   /*-- edit some of its internal parameters --*/
   ii = EDIT_dset_items(
           new_dset ,
              ADN_prefix      , new_prefix ,           /* filename prefix */
              ADN_malloc_type , DATABLOCK_MEM_MALLOC , /* store in memory */
              ADN_datum_all   , new_datum ,            /* atomic datum */
              ADN_nvals       , maxlength ,            /* # sub-bricks */
              ADN_ntt         , maxlength ,            /* # time points */
           /*   ADN_ttorg       , old_dtime ,  */              /* time origin */
           /*   ADN_ttdel       , old_dtime ,  */            /* time step */
           /*   ADN_ttdur       , old_dtime ,  */            /* time duration */
           /*   ADN_nsl         , 0 ,          */        /* z-axis time slicing */
           /*   ADN_tunits      , old_units ,  */        /* time units */
           ADN_none ) ;

   if( ii != 0 ){
      THD_delete_3dim_dataset( new_dset , False ) ;
      FREE_WORKSPACE ;
      return "***********************************\n"
             "Error while creating output dataset\n"
             "***********************************"  ;
   }


   /*------------------------------------------------------------*/
   /*------- The output is now in fout[kk][ii],
             for kk=0..maxlength-1 , ii=0..nvox-1.
             We must now put this into the output dataset -------*/

   switch( new_datum ){

      /*** output is floats is the simplest:
           we just have to attach the fout bricks to the dataset ***/

      case MRI_float:
         for( kk=0 ; kk < maxlength ; kk++ )
            EDIT_substitute_brick( new_dset , kk , MRI_float , fout[kk] ) ;
      break ;

      /*** output is shorts:
           we have to create a scaled sub-brick from fout ***/

      case MRI_short:{
         short * bout ;
         float fac ; 

         for( kk=0 ; kk < maxlength ; kk++ ){  /* loop over sub-bricks */

            /*-- get output sub-brick --*/
            bout = (short *) malloc( sizeof(short) * nvox ) ;
            if( bout == NULL ){
               fprintf(stderr,"\nFinal malloc error in plug_stavg!\n\a") ;
               return("Final malloc error in plug_stavg!"); ;
               /*  exit(1) ;*/
            }

            /*-- find scaling and then scale --*/
            /*fac = MCW_vol_amax( nvox,1,1 , MRI_float , fout[kk] ) ;*/
            fac = 1.0;
            EDIT_coerce_scale_type( nvox,fac ,
                                    MRI_float,fout[kk] , MRI_short,bout ) ;
            free( fout[kk] ) ;  /* don't need this anymore */

            /*-- put output brick into dataset, and store scale factor --*/
            EDIT_substitute_brick( new_dset , kk , MRI_short , bout ) ;
         }
      }
      break ;

      /*** output is bytes (byte = unsigned char)
           we have to create a scaled sub-brick from fout ***/

      case MRI_byte:{
         byte * bout ;
         float fac ;

         for( kk=0 ; kk < maxlength ; kk++ ){  /* loop over sub-bricks */

            /*-- get output sub-brick --*/

            bout = (byte *) malloc( sizeof(byte) * nvox ) ;
            if( bout == NULL ){
               fprintf(stderr,"\nFinal malloc error in plug_stavg!\n\a") ;
               return("Final malloc error in plug_stavg!"); ;
	       /*               exit(1) ;*/
            }

            /*-- find scaling and then scale --*/

            fac = 1.0;
            EDIT_coerce_scale_type( nvox,fac ,
                                    MRI_float,fout[kk] , MRI_byte,bout ) ;

            free( fout[kk] ) ;  /* don't need this anymore */

            /*-- put output brick into dataset, and store scale factor --*/

            EDIT_substitute_brick( new_dset , kk , MRI_byte , bout ) ;
         }

      }
      break ;

   } /* end of switch on output data type */

   /*-------------- Cleanup and go home ----------------*/

   PLUTO_set_meter( plint , 100 ) ;  /* set progress meter to 100% */

   PLUTO_add_dset( plint , new_dset , DSET_ACTION_MAKE_CURRENT ) ;

   FREE_WORKSPACE ;
   return NULL ;  /* null string returned means all was OK */
}
Exemple #22
0
int main( int argc , char *argv[] )
{
   int nx,ny,nz , nxyz , ii,kk , num1,num2 , num_tt=0 , iv ,
       piece , fim_offset;
   float dx,dy,dz , dxyz ,
         num1_inv=0.0 , num2_inv , num1m1_inv=0.0 , num2m1_inv , dof ,
         dd,tt,q1,q2 , f1,f2 , tt_max=0.0 ;
   THD_3dim_dataset *dset=NULL , *new_dset=NULL ;
   THD_3dim_dataset * base_dset;
   float *av1 , *av2 , *sd1 , *sd2 , *ffim , *gfim ;
   float *base_ary=NULL;

   void  *vsp ;
   void  *vdif ;           /* output mean difference */
   char  cbuf[THD_MAX_NAME] ;
   float fbuf[MAX_STAT_AUX] , fimfac ;
   int   output_datum ;
   float npiece , memuse ;

   float *dofbrik=NULL , *dofar=NULL ;
   THD_3dim_dataset *dof_dset=NULL ;

   /*-- read command line arguments --*/

   if( argc < 2 || strncmp(argv[1],"-help",5) == 0 ) TT_syntax(NULL) ;

   /*-- 20 Apr 2001: addto the arglist, if user wants to [RWCox] --*/

   mainENTRY("3dttest main"); machdep() ; PRINT_VERSION("3dttest") ;
   INFO_message("For most purposes, 3dttest++ should be used instead of 3dttest!") ;

   { int new_argc ; char ** new_argv ;
     addto_args( argc , argv , &new_argc , &new_argv ) ;
     if( new_argv != NULL ){ argc = new_argc ; argv = new_argv ; }
   }

   AFNI_logger("3dttest",argc,argv) ;

   TT_read_opts( argc , argv ) ;

   if( ! TT_be_quiet )
      printf("3dttest: t-tests of 3D datasets, by RW Cox\n") ;

   /*-- read first dataset in set2 to get dimensions, etc. --*/

   dset = THD_open_dataset( TT_set2->ar[0] ) ;  /* 20 Dec 1999  BDW */
   if( ! ISVALID_3DIM_DATASET(dset) )
     ERROR_exit("Unable to open dataset file %s",TT_set2->ar[0]);

   nx = dset->daxes->nxx ;
   ny = dset->daxes->nyy ;
   nz = dset->daxes->nzz ;         nxyz = nx * ny * nz ;
   dx = fabs(dset->daxes->xxdel) ;
   dy = fabs(dset->daxes->yydel) ;
   dz = fabs(dset->daxes->zzdel) ; dxyz = dx * dy * dz ;

#ifdef TTDEBUG
printf("*** nx=%d ny=%d nz=%d\n",nx,ny,nz) ;
#endif

   /*-- make an empty copy of this dataset, for eventual output --*/

#ifdef TTDEBUG
printf("*** making empty dataset\n") ;
#endif

   new_dset = EDIT_empty_copy( dset ) ;

   tross_Make_History( "3dttest" , argc,argv , new_dset ) ;

   strcpy( cbuf , dset->self_name ) ; strcat( cbuf , "+TT" ) ;

   iv = DSET_PRINCIPAL_VALUE(dset) ;

   if( TT_datum >= 0 ){
      output_datum = TT_datum ;
   } else {
      output_datum = DSET_BRICK_TYPE(dset,iv) ;
      if( output_datum == MRI_byte ) output_datum = MRI_short ;
   }

#ifdef TTDEBUG
printf(" ** datum = %s\n",MRI_TYPE_name[output_datum]) ;
#endif

   iv = EDIT_dset_items( new_dset ,
                           ADN_prefix , TT_prefix ,
                           ADN_label1 , TT_prefix ,
                           ADN_directory_name , TT_session ,
                           ADN_self_name , cbuf ,
                           ADN_type , ISHEAD(dset) ? HEAD_FUNC_TYPE : GEN_FUNC_TYPE ,
                           ADN_func_type , FUNC_TT_TYPE ,
                           ADN_nvals , FUNC_nvals[FUNC_TT_TYPE] ,
                           ADN_ntt , 0 ,                           /* 07 Jun 2007 */
                           ADN_datum_all , output_datum ,
                         ADN_none ) ;

   if( iv > 0 )
     ERROR_exit("%d errors in attempting to create output dataset!",iv ) ;

   if( THD_deathcon() && THD_is_file(new_dset->dblk->diskptr->header_name) )
      ERROR_exit(
              "Output dataset file %s already exists--cannot continue!\a",
              new_dset->dblk->diskptr->header_name ) ;

#ifdef TTDEBUG
printf("*** deleting exemplar dataset\n") ;
#endif

   THD_delete_3dim_dataset( dset , False ) ; dset = NULL ;

/** macro to test a malloc-ed pointer for validity **/

#define MTEST(ptr) \
   if((ptr)==NULL) \
      ( fprintf(stderr,"*** Cannot allocate memory for statistics!\n"), exit(0) )

   /*-- make space for the t-test computations --*/

   /* (allocate entire volumes) 13 Dec 2005 [rickr] */
                              npiece  = 3.0 ;  /* need at least this many */
   if( TT_paired )            npiece += 1.0 ;
   else if( TT_set1 != NULL ) npiece += 2.0 ;

   npiece += mri_datum_size(output_datum) / (float) sizeof(float) ;
   npiece += mri_datum_size(output_datum) / (float) sizeof(float) ;

#if 0
   piece_size = TT_workmem * MEGA / ( npiece * sizeof(float) ) ;
   if( piece_size > nxyz ) piece_size = nxyz ;

#ifdef TTDEBUG
printf("*** malloc-ing space for statistics: %g float arrays of length %d\n",
       npiece,piece_size) ;
#endif
#endif

   av2  = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(av2) ;
   sd2  = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(sd2) ;
   ffim = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(ffim) ;
   num2 = TT_set2->num ;

   if( TT_paired ){
      av1  = sd1 = NULL ;
      gfim = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(gfim) ;
      num1 = num2 ;
   } else if( TT_set1 != NULL ){
      av1  = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(av1) ;
      sd1  = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(sd1) ;
      gfim = NULL ;
      num1 = TT_set1->num ;
   } else {
      av1  = sd1 = NULL ;
      gfim = NULL ;
      num1 = 0 ;
   }

   vdif = (void *) malloc( mri_datum_size(output_datum) * nxyz ) ; MTEST(vdif) ;
   vsp  = (void *) malloc( mri_datum_size(output_datum) * nxyz ) ; MTEST(vsp)  ;

   /* 27 Dec 2002: make DOF dataset (if prefix is given, and unpooled is on) */

   if( TT_pooled == 0 && TT_dof_prefix[0] != '\0' ){
     dofbrik = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(dofbrik) ;

     dof_dset = EDIT_empty_copy( new_dset ) ;

     tross_Make_History( "3dttest" , argc,argv , dof_dset ) ;

     EDIT_dset_items( dof_dset ,
                       ADN_prefix , TT_dof_prefix ,
                       ADN_directory_name , TT_session ,
                       ADN_type , ISHEAD(dset) ? HEAD_FUNC_TYPE : GEN_FUNC_TYPE,
                       ADN_func_type , FUNC_BUCK_TYPE ,
                       ADN_nvals , 1 ,
                       ADN_datum_all , MRI_float ,
                      ADN_none ) ;

     if( THD_is_file(dof_dset->dblk->diskptr->header_name) )
        ERROR_exit(
                "-dof_prefix dataset file %s already exists--cannot continue!\a",
                dof_dset->dblk->diskptr->header_name ) ;

     EDIT_substitute_brick( dof_dset , 0 , MRI_float , dofbrik ) ;
   }

   /* print out memory usage to edify the user */

   if( ! TT_be_quiet ){
      memuse =    sizeof(float) * nxyz * npiece
              + ( mri_datum_size(output_datum) + sizeof(short) ) * nxyz ;

      if( dofbrik != NULL ) memuse += sizeof(float) * nxyz ;  /* 27 Dec 2002 */

      printf("--- allocated %d Megabytes memory for internal use (%d volumes)\n",
             (int)(memuse/MEGA), (int)npiece) ;
   }

   mri_fix_data_pointer( vdif , DSET_BRICK(new_dset,0) ) ;  /* attach bricks */
   mri_fix_data_pointer( vsp  , DSET_BRICK(new_dset,1) ) ;  /* to new dataset */

   /** only short and float are allowed for output **/
   if( output_datum != MRI_short && output_datum != MRI_float )
      ERROR_exit("Illegal output data type %d = %s",
                 output_datum , MRI_TYPE_name[output_datum] ) ;

   num2_inv = 1.0 / num2 ;  num2m1_inv = 1.0 / (num2-1) ;
   if( num1 > 0 ){
      num1_inv = 1.0 / num1 ;  num1m1_inv = 1.0 / (num1-1) ;
   }

   /*----- loop over pieces to process the input datasets with -----*/

/** macro to open a dataset and make it ready for processing **/

#define DOPEN(ds,name)                                                            \
   do{ int pv ; (ds) = THD_open_dataset((name)) ;  /* 16 Sep 1999 */              \
       if( !ISVALID_3DIM_DATASET((ds)) )                                          \
          ERROR_exit("Can't open dataset: %s",(name)) ;                           \
       if( (ds)->daxes->nxx!=nx || (ds)->daxes->nyy!=ny || (ds)->daxes->nzz!=nz ) \
          ERROR_exit("Axes size mismatch: %s",(name)) ;                           \
       if( !EQUIV_GRIDS((ds),new_dset) )                                          \
          WARNING_message("Grid mismatch: %s",(name)) ;                           \
       if( DSET_NUM_TIMES((ds)) > 1 )                                             \
         ERROR_exit("Can't use time-dependent data: %s",(name)) ;                 \
       if( TT_use_editor ) EDIT_one_dataset( (ds), &TT_edopt ) ;                  \
       else                DSET_load((ds)) ;                                      \
       pv = DSET_PRINCIPAL_VALUE((ds)) ;                                          \
       if( DSET_ARRAY((ds),pv) == NULL )                                          \
          ERROR_exit("Can't access data: %s",(name)) ;                            \
       if( DSET_BRICK_TYPE((ds),pv) == MRI_complex )                              \
          ERROR_exit("Can't use complex data: %s",(name)) ;                       \
       break ; } while (0)

#if 0   /* can do it directly now (without offsets)  13 Dec 2005 [rickr] */
/** macro to return pointer to correct location in brick for current processing **/

#define SUB_POINTER(ds,vv,ind,ptr)                                            \
   do{ switch( DSET_BRICK_TYPE((ds),(vv)) ){                                  \
         default: ERROR_exit("Illegal datum! ***");                           \
            case MRI_short:{ short * fim = (short *) DSET_ARRAY((ds),(vv)) ;  \
                            (ptr) = (void *)( fim + (ind) ) ;                 \
            } break ;                                                         \
            case MRI_byte:{ byte * fim = (byte *) DSET_ARRAY((ds),(vv)) ;     \
                            (ptr) = (void *)( fim + (ind) ) ;                 \
            } break ;                                                         \
            case MRI_float:{ float * fim = (float *) DSET_ARRAY((ds),(vv)) ;  \
                             (ptr) = (void *)( fim + (ind) ) ;                \
            } break ; } break ; } while(0)
#endif

   /** number of pieces to process **/
   /* num_piece = (nxyz + piece_size - 1) / nxyz ; */

#if 0
   nice(2) ;  /** lower priority a little **/
#endif


   /* possibly open TT_base_dset now, and convert to floats */
   if( TT_base_dname ) {
      DOPEN(base_dset, TT_base_dname) ;
      base_ary = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(base_ary) ;
      EDIT_coerce_scale_type(nxyz , DSET_BRICK_FACTOR(base_dset,0) ,
              DSET_BRICK_TYPE(base_dset,0),DSET_ARRAY(base_dset,0), /* input */
              MRI_float ,base_ary  ) ;                              /* output */
      THD_delete_3dim_dataset( base_dset , False ) ; base_dset = NULL ;
   }

   /* only 1 'piece' now   13 Dec 2005 [rickr] */
   for( piece=0 ; piece < 1 ; piece++ ){

      fim_offset = 0 ;

#ifdef TTDEBUG
printf("*** start of piece %d: length=%d offset=%d\n",piece,nxyz,fim_offset) ;
#else
      if( ! TT_be_quiet ){
         printf("--- starting piece %d/%d (%d voxels) ",piece+1,1,nxyz) ;
         fflush(stdout) ;
      }
#endif

      /** process set2 (and set1, if paired) **/

      for( ii=0 ; ii < nxyz ; ii++ ) av2[ii] = 0.0 ;
      for( ii=0 ; ii < nxyz ; ii++ ) sd2[ii] = 0.0 ;

      for( kk=0 ; kk < num2 ; kk++ ){

         /** read in the data **/

         DOPEN(dset,TT_set2->ar[kk]) ;
         iv = DSET_PRINCIPAL_VALUE(dset) ;

#ifndef TTDEBUG
         if( ! TT_be_quiet ){ printf(".") ; fflush(stdout) ; }  /* progress */
#else
         printf(" ** opened dataset file %s\n",TT_set2->ar[kk]);
#endif

#if 0 /* fimfac will be compute when the results are ready */
         if( piece == 0 && kk == 0 ){
            fimfac = DSET_BRICK_FACTOR(dset,iv) ;
            if( fimfac == 0.0 ) fimfac = 1.0 ;
            fimfacinv = 1.0 / fimfac ;
#ifdef TTDEBUG
printf(" ** set fimfac = %g\n",fimfac) ;
#endif
         }
#endif

         /** convert it to floats (in ffim) **/
         EDIT_coerce_scale_type(nxyz , DSET_BRICK_FACTOR(dset,iv) ,
                                DSET_BRICK_TYPE(dset,iv),DSET_ARRAY(dset,iv), /* input */
                                MRI_float ,ffim  ) ;                         /* output */
         THD_delete_3dim_dataset( dset , False ) ; dset = NULL ;

         /** get the paired dataset, if present **/

         if( TT_paired ){
            DOPEN(dset,TT_set1->ar[kk]) ;
            iv = DSET_PRINCIPAL_VALUE(dset) ;

#ifndef TTDEBUG
         if( ! TT_be_quiet ){ printf(".") ; fflush(stdout) ; }  /* progress */
#else
        printf(" ** opened dataset file %s\n",TT_set1->ar[kk]);
#endif

            EDIT_coerce_scale_type(
                        nxyz , DSET_BRICK_FACTOR(dset,iv) ,
                        DSET_BRICK_TYPE(dset,iv),DSET_ARRAY(dset,iv), /* input */
                        MRI_float ,gfim  ) ;                         /* output */
            THD_delete_3dim_dataset( dset , False ) ; dset = NULL ;

            if( TT_voxel >= 0 )
              fprintf(stderr,"-- paired values #%02d: %f, %f\n",
                      kk,ffim[TT_voxel],gfim[TT_voxel]) ;

            for( ii=0 ; ii < nxyz ; ii++ ) ffim[ii] -= gfim[ii] ;
         } else if( TT_voxel >= 0 )
            fprintf(stderr,"-- set2 value #%02d: %f\n",kk,ffim[TT_voxel]);

#ifdef TTDEBUG
printf("  * adding into av2 and sd2\n") ;
#endif

         /* accumulate into av2 and sd2 */

         for( ii=0 ; ii < nxyz ; ii++ ){
            dd = ffim[ii] ; av2[ii] += dd ; sd2[ii] += dd * dd ;
         }

      }  /* end of loop over set2 datasets */

      /** form the mean and stdev of set2 **/

#ifdef TTDEBUG
printf(" ** forming mean and sigma of set2\n") ;
#endif

      for( ii=0 ; ii < nxyz ; ii++ ){
         av2[ii] *= num2_inv ;
         dd       = (sd2[ii] - num2*av2[ii]*av2[ii]) ;
         sd2[ii]  = (dd > 0.0) ? sqrt( num2m1_inv * dd ) : 0.0 ;
      }
      if( TT_voxel >= 0 )
         fprintf(stderr,"-- s2 mean = %g, sd = %g\n",
                 av2[TT_voxel],sd2[TT_voxel]) ;

      /** if set1 exists but is not paired with set2, process it now **/

      if( ! TT_paired && TT_set1 != NULL ){

         for( ii=0 ; ii < nxyz ; ii++ ) av1[ii] = 0.0 ;
         for( ii=0 ; ii < nxyz ; ii++ ) sd1[ii] = 0.0 ;

         for( kk=0 ; kk < num1 ; kk++ ){
            DOPEN(dset,TT_set1->ar[kk]) ;
            iv = DSET_PRINCIPAL_VALUE(dset) ;

#ifndef TTDEBUG
         if( ! TT_be_quiet ){ printf(".") ; fflush(stdout) ; }  /* progress */
#else
         printf(" ** opened dataset file %s\n",TT_set1->ar[kk]);
#endif

            EDIT_coerce_scale_type(
                                nxyz , DSET_BRICK_FACTOR(dset,iv) ,
                                DSET_BRICK_TYPE(dset,iv),DSET_ARRAY(dset,iv), /* input */
                                MRI_float ,ffim  ) ;                         /* output */
            THD_delete_3dim_dataset( dset , False ) ; dset = NULL ;

#ifdef TTDEBUG
printf("  * adding into av1 and sd1\n") ;
#endif

            for( ii=0 ; ii < nxyz ; ii++ ){
               dd = ffim[ii] ; av1[ii] += dd ; sd1[ii] += dd * dd ;
            }
            if( TT_voxel >= 0 )
               fprintf(stderr,"-- set1 value #%02d: %g\n",kk,ffim[TT_voxel]) ;
         }  /* end of loop over set1 datasets */

         /** form the mean and stdev of set1 **/

#ifdef TTDEBUG
printf(" ** forming mean and sigma of set1\n") ;
#endif

         for( ii=0 ; ii < nxyz ; ii++ ){
            av1[ii] *= num1_inv ;
            dd       = (sd1[ii] - num1*av1[ii]*av1[ii]) ;
            sd1[ii]  = (dd > 0.0) ? sqrt( num1m1_inv * dd ) : 0.0 ;
         }
         if( TT_voxel >= 0 )
            fprintf(stderr,"-- s1 mean = %g, sd = %g\n",
                    av1[TT_voxel], sd1[TT_voxel]) ;
      }  /* end of processing set1 by itself */

      /***** now form difference and t-statistic *****/

#ifndef TTDEBUG
         if( ! TT_be_quiet ){ printf("+") ; fflush(stdout) ; }  /* progress */
#else
         printf(" ** computing t-tests next\n") ;
#endif

#if 0 /* will do at end using EDIT_convert_dtype  13 Dec 2005 [rickr] */

      /** macro to assign difference value to correct type of array **/
#define DIFASS switch( output_datum ){                                        \
                 case MRI_short: sdar[ii] = (short) (fimfacinv*dd) ; break ;  \
                 case MRI_float: fdar[ii] = (float) dd             ; break ; }
#define TOP_SS  32700
#define TOP_TT (32700.0/FUNC_TT_SCALE_SHORT)

#endif

      if( TT_paired || TT_use_bval == 1 ){ /** case 1: paired estimate or 1-sample **/

        if( TT_paired || TT_n1 == 0 ){       /* the olde waye: 1 sample test */
          f2 = 1.0 / sqrt( (double) num2 ) ;
          for( ii=0 ; ii < nxyz ; ii++ ){
            av2[ii] -= (base_ary ? base_ary[ii] : TT_bval) ;  /* final mean */
            if( sd2[ii] > 0.0 ){
               num_tt++ ;
               tt      = av2[ii] / (f2 * sd2[ii]) ;
               sd2[ii] = tt;      /* final t-stat */

               tt = fabs(tt) ; if( tt > tt_max ) tt_max = tt ;
            } else {
               sd2[ii] = 0.0;
            }
          }
          if( TT_voxel >= 0 )
             fprintf(stderr,"-- paired/bval mean = %g, t = %g\n",
                     av2[TT_voxel], sd2[TT_voxel]) ;

        } else {  /* 10 Oct 2007: -sdn1 was used with -base1: 'two' sample test */
          f1 = (TT_n1-1.0) * (1.0/TT_n1 + 1.0/num2) / (TT_n1+num2-2.0) ;
          f2 = (num2 -1.0) * (1.0/TT_n1 + 1.0/num2) / (TT_n1+num2-2.0) ;
          for( ii=0 ; ii < nxyz ; ii++ ){
            av2[ii] -= (base_ary ? base_ary[ii] : TT_bval) ;  /* final mean */
            q1 = f1 * TT_sd1*TT_sd1 + f2 * sd2[ii]*sd2[ii] ;
            if( q1 > 0.0 ){
              num_tt++ ;
              tt = av2[ii] / sqrt(q1) ;
              sd2[ii] = tt ;      /* final t-stat */
              tt = fabs(tt) ; if( tt > tt_max ) tt_max = tt ;
            } else {
              sd2[ii] = 0.0 ;
            }
          }
        } /* end of -sdn1 special case */
#ifdef TTDEBUG
printf(" ** paired or bval test: num_tt = %d\n",num_tt) ;
#endif

      } else if( TT_pooled ){ /** case 2: unpaired 2-sample, pooled variance **/

         f1 = (num1-1.0) * (1.0/num1 + 1.0/num2) / (num1+num2-2.0) ;
         f2 = (num2-1.0) * (1.0/num1 + 1.0/num2) / (num1+num2-2.0) ;
         for( ii=0 ; ii < nxyz ; ii++ ){
            av2[ii] -= av1[ii] ;        /* final mean */
            q1 = f1 * sd1[ii]*sd1[ii] + f2 * sd2[ii]*sd2[ii] ;
            if( q1 > 0.0 ){
               num_tt++ ;
               tt = av2[ii] / sqrt(q1) ;
               sd2[ii] = tt ;      /* final t-stat */

               tt = fabs(tt) ; if( tt > tt_max ) tt_max = tt ;
            } else {
               sd2[ii] = 0.0 ;
            }
         }

         if( TT_voxel >= 0 )
            fprintf(stderr,"-- unpaired, pooled mean = %g, t = %g\n",
                    av2[TT_voxel], sd2[TT_voxel]) ;
#ifdef TTDEBUG
printf(" ** pooled test: num_tt = %d\n",num_tt) ;
#endif

      } else { /** case 3: unpaired 2-sample, unpooled variance **/
               /** 27 Dec 2002: modified to save DOF into dofar **/

         if( dofbrik != NULL ) dofar = dofbrik + fim_offset ;  /* 27 Dec 2002 */

         for( ii=0 ; ii < nxyz ; ii++ ){
            av2[ii] -= av1[ii] ;
            q1 = num1_inv * sd1[ii]*sd1[ii] ;
            q2 = num2_inv * sd2[ii]*sd2[ii] ;
            if( q1>0.0 && q2>0.0 ){               /* have positive variances? */
               num_tt++ ;
               tt = av2[ii] / sqrt(q1+q2) ;
               sd2[ii] = tt ;      /* final t-stat */

               tt = fabs(tt) ; if( tt > tt_max ) tt_max = tt ;

               if( dofar != NULL )                             /* 27 Dec 2002 */
                 dofar[ii] =  (q1+q2)*(q1+q2)
                            / (num1m1_inv*q1*q1 + num2m1_inv*q2*q2) ;
            } else {
               sd2[ii] = 0.0 ;
               if( dofar != NULL ) dofar[ii] = 1.0 ;           /* 27 Dec 2002 */
            }
         }

         if( TT_voxel >= 0 )
            fprintf(stderr,"-- unpaired, unpooled mean = %g, t = %g\n",
                    av2[TT_voxel], sd2[TT_voxel]) ;
#ifdef TTDEBUG
printf(" ** unpooled test: num_tt = %d\n",num_tt) ;
#endif
      }

#ifndef TTDEBUG
         if( ! TT_be_quiet ){ printf("\n") ; fflush(stdout) ; }
#endif

   }  /* end of loop over pieces of the input */

   if( TT_paired ){
      printf("--- Number of degrees of freedom = %d (paired test)\n",num2-1) ;
      dof = num2 - 1 ;
   } else if( TT_use_bval == 1 ){
      if( TT_n1 == 0 ){
        printf("--- Number of degrees of freedom = %d (1-sample test)\n",num2-1) ;
        dof = num2 - 1 ;
      } else {
        dof = TT_n1+num2-2 ;
        printf("--- Number of degrees of freedom = %d (-sdn1 2-sample test)\n",(int)dof) ;
      }
   } else {
      printf("--- Number of degrees of freedom = %d (2-sample test)\n",num1+num2-2) ;
      dof = num1+num2-2 ;
      if( ! TT_pooled )
         printf("    (For unpooled variance estimate, this is only approximate!)\n") ;
   }

   printf("--- Number of t-tests performed  = %d out of %d voxels\n",num_tt,nxyz) ;
   printf("--- Largest |t| value found      = %g\n",tt_max) ;

   kk = sizeof(ptable) / sizeof(float) ;
   for( ii=0 ; ii < kk ; ii++ ){
      tt = student_p2t( ptable[ii] , dof ) ;
      printf("--- Double sided tail p = %8f at t = %8f\n" , ptable[ii] , tt ) ;
   }

   /**----------------------------------------------------------------------**/
   /** now convert data to output format                13 Dec 2005 [rickr] **/

   /* first set mean */
   fimfac = EDIT_convert_dtype(nxyz , MRI_float,av2 , output_datum,vdif , 0.0) ;
   DSET_BRICK_FACTOR(new_dset, 0) = (fimfac != 0.0) ? 1.0/fimfac : 0.0 ;
   dd = fimfac; /* save for debug output */

   /* if output is of type short, limit t-stat magnitude to 32.7 */
   if( output_datum == MRI_short ){
     for( ii=0 ; ii < nxyz ; ii++ ){
       if     ( sd2[ii] >  32.7 ) sd2[ii] =  32.7 ;
       else if( sd2[ii] < -32.7 ) sd2[ii] = -32.7 ;
     }
   }

   fimfac = EDIT_convert_dtype(nxyz , MRI_float,sd2 , output_datum,vsp , 0.0) ;
   DSET_BRICK_FACTOR(new_dset, 1) = (fimfac != 0.0) ? 1.0/fimfac : 0.0 ;

#ifdef TTDEBUG
printf(" ** fimfac for mean, t-stat = %g, %g\n",dd, fimfac) ;
#endif
   /**----------------------------------------------------------------------**/

   INFO_message("Writing combined dataset into %s\n", DSET_BRIKNAME(new_dset) ) ;

   fbuf[0] = dof ;
   for( ii=1 ; ii < MAX_STAT_AUX ; ii++ ) fbuf[ii] = 0.0 ;
   (void) EDIT_dset_items( new_dset , ADN_stat_aux , fbuf , ADN_none ) ;

#if 0 /* factors already set */
   fbuf[0] = (output_datum == MRI_short && fimfac != 1.0 ) ? fimfac                    : 0.0 ;
   fbuf[1] = (output_datum == MRI_short                  ) ? 1.0 / FUNC_TT_SCALE_SHORT : 0.0 ;
   (void) EDIT_dset_items( new_dset , ADN_brick_fac , fbuf , ADN_none ) ;
#endif

   if( !AFNI_noenv("AFNI_AUTOMATIC_FDR") ) ii = THD_create_all_fdrcurves(new_dset) ;
   else                                    ii = 0 ;
   THD_load_statistics( new_dset ) ;
   THD_write_3dim_dataset( NULL,NULL , new_dset , True ) ;
   if( ii > 0 ) ININFO_message("created %d FDR curves in header",ii) ;

   if( dof_dset != NULL ){                                  /* 27 Dec 2002 */
     DSET_write( dof_dset ) ;
     WROTE_DSET( dof_dset ) ;
   }

   exit(0) ;
}
Exemple #23
0
/*
 * create empty count dataset
 * for each input dataset and each sub-volume
 *    for each voxel, if set: increment
 * close datasets as they are processed
 */
int count_masks(THD_3dim_dataset * dsets[], int ndsets, int verb, /* inputs */
                THD_3dim_dataset ** cset, int * nvol)             /* outputs */
{
   THD_3dim_dataset * dset;
   short * counts = NULL;             /* will become data for returned cset */
   byte  * bptr;                      /* always points to mask volumes      */
   int     nxyz, iset, ivol, ixyz;

   ENTRY("count_masks");

   if( !dsets || !cset || !nvol )
      ERROR_exit("NULL inputs to count_masks");

   if( ndsets <= 0 ) {
      ERROR_message("count_masks: no input datasets");
      RETURN(1);
   }

   *nvol = 0;
   nxyz = DSET_NVOX(dsets[0]);
   
   /* allocate memory for the counts */
   counts = (short *)calloc(nxyz, sizeof(short));
   if( !counts ) ERROR_exit("failed to malloc %d shorts", nxyz);

   /* for each volume of each dataset, count set voxels */
   for( iset=0; iset < ndsets; iset++ ) {
      dset = dsets[iset];
      *nvol += DSET_NVALS(dset);        /* accumulate num volumes */

      /* for each volume in this dataset, count set voxels */
      for( ivol=0; ivol < DSET_NVALS(dset); ivol++ ) {
         if( DSET_BRICK_TYPE(dset, ivol) != MRI_byte )
            ERROR_exit("in count_masks with non-byte data (set %d, vol %d)",
                       iset, ivol);

         bptr = DBLK_ARRAY(dset->dblk, ivol);
         for( ixyz = 0; ixyz < nxyz; ixyz++ ) 
            if( bptr[ixyz] ) counts[ixyz]++;
      }

      if( iset > 0 ) DSET_delete(dset); /* close the first one at end */
   }  /* dataset */

   if( verb > 1 ) {
      int maxval;
      for( maxval=counts[0], ixyz=1; ixyz < nxyz; ixyz++ )
         if( counts[ixyz] > maxval ) maxval = counts[ixyz];

      INFO_message("counted %d mask volumes in %d datasets (%d voxels)\n",
                   *nvol, ndsets, nxyz);
      INFO_message("   (maximum overlap = %d)\n", maxval);
   }

   if( *nvol >= (1<<15) )
      WARNING_message("too many volumes to count as shorts: %d", *nvol);

   /* create output dataset */
   *cset = EDIT_empty_copy(dsets[0]);
   EDIT_dset_items(*cset, ADN_nvals, 1,  ADN_ntt, 0, ADN_none);
   EDIT_substitute_brick(*cset, 0, MRI_short, counts);

   DSET_delete(dsets[0]);  /* now finished with first dataset */

   RETURN(0);
}
int main( int argc , char *argv[] )
{
   int iarg=1 , ii , do_iwarp=0 ;
   char *prefix = "NwarpCat" ;
   mat44 wmat , smat , qmat ;
   THD_3dim_dataset *oset=NULL ;
   char *cwarp_all=NULL ; int ntot=0 ;

   AFNI_SETUP_OMP(0) ;  /* 24 Jun 2013 */

   if( argc < 2 || strcasecmp(argv[1],"-help") == 0 ) NWC_help() ;

   /*-- bureaucracy --*/

   mainENTRY("3dNwarpCat"); machdep();
   AFNI_logger("3dNwarpCat",argc,argv);
   PRINT_VERSION("3dNwarpCat"); AUTHOR("Zhark the Warper");
   (void)COX_clock_time() ;
   putenv("AFNI_WSINC5_SILENT=YES") ;

   /*-- initialization --*/

   CW_no_expad = 1 ;  /* don't allow automatic padding of input warp */
   Hverb = 0 ;        /* don't be verbose inside mri_nwarp.c */
   for( ii=0 ; ii < NWMAX ; ii++ ) cwarp[ii] = NULL ;

   /*-- scan args --*/

   while( iarg < argc && argv[iarg][0] == '-' ){

     /*---------------*/

     if( strcasecmp(argv[iarg],"-iwarp") == 0 ){
       do_iwarp = 1 ; iarg++ ; continue ;
     }

     /*---------------*/

     if( strcasecmp(argv[iarg],"-space") == 0 ){
       sname = strdup(argv[++iarg]) ; iarg++ ; continue ;
     }

     /*---------------*/

     if( strcasecmp(argv[iarg],"-NN") == 0 || strncasecmp(argv[iarg],"-nearest",6) == 0 ){
       WARNING_message("NN interpolation not legal here -- switched to linear") ;
       interp_code = MRI_LINEAR ; iarg++ ; continue ;
     }
     if( strncasecmp(argv[iarg],"-linear",4)==0 || strncasecmp(argv[iarg],"-trilinear",6)==0 ){
       interp_code = MRI_LINEAR ; iarg++ ; continue ;
     }
     if( strncasecmp(argv[iarg],"-cubic",4)==0 || strncasecmp(argv[iarg],"-tricubic",6)==0 ){
       WARNING_message("cubic interplation not legal here -- switched to quintic") ;
       interp_code = MRI_QUINTIC ; iarg++ ; continue ;
     }
     if( strncasecmp(argv[iarg],"-quintic",4)==0 || strncasecmp(argv[iarg],"-triquintic",6)==0 ){
       interp_code = MRI_QUINTIC ; iarg++ ; continue ;
     }
     if( strncasecmp(argv[iarg],"-wsinc",5) == 0 ){
       interp_code = MRI_WSINC5 ; iarg++ ; continue ;
     }

     /*---------------*/

     if( strcasecmp(argv[iarg],"-expad") == 0 ){
       int expad ;
       if( ++iarg >= argc ) ERROR_exit("no argument after '%s' :-(",argv[iarg-1]) ;
       expad = (int)strtod(argv[iarg],NULL) ;
       if( expad < 0 ){
         WARNING_message("-expad %d is illegal and is set to zero",expad) ;
         expad = 0 ;
       }
       CW_extra_pad = expad ;  /* this is how we force extra padding */
       iarg++ ; continue ;
     }

     /*---------------*/

     if( strncasecmp(argv[iarg],"-interp",5)==0 ){
       char *inam ;
       if( ++iarg >= argc ) ERROR_exit("no argument after '%s' :-(",argv[iarg-1]) ;
       inam = argv[iarg] ; if( *inam == '-' ) inam++ ;
       if( strcasecmp(inam,"NN")==0 || strncasecmp(inam,"nearest",5)==0 ){
         WARNING_message("NN interpolation not legal here -- changed to linear") ;
         interp_code = MRI_LINEAR ;
       } else if( strncasecmp(inam,"linear",3)==0 || strncasecmp(inam,"trilinear",5)==0 ){
         interp_code = MRI_LINEAR ;
       } else if( strncasecmp(inam,"cubic",3)==0 || strncasecmp(inam,"tricubic",5)==0 ){
         WARNING_message("cubic interplation not legal here -- changed to quintic") ;
         interp_code = MRI_QUINTIC ;
       } else if( strncasecmp(inam,"quintic",3)==0 || strncasecmp(inam,"triquintic",5)==0 ){
         interp_code = MRI_QUINTIC ;
       } else if( strncasecmp(inam,"wsinc",4)==0 ){
         interp_code = MRI_WSINC5 ;
       } else {
         ERROR_exit("Unknown code '%s' after '%s' :-(",argv[iarg],argv[iarg-1]) ;
       }
       iarg++ ; continue ;
     }

     /*---------------*/

     if( strcasecmp(argv[iarg],"-verb") == 0 ){
       verb++ ; NwarpCalcRPN_verb(verb) ; iarg++ ; continue ;
     }

     /*---------------*/

     if( strcasecmp(argv[iarg],"-prefix") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("no argument after '%s' :-(",argv[iarg-1]) ;
       prefix = argv[iarg] ;
       if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal name after '%s'",argv[iarg-1]) ;
       iarg++ ; continue ;
     }

     /*---------------*/

     if( strncasecmp(argv[iarg],"-warp",5) == 0 ){
       int nn ;
       if( iarg >= argc-1 ) ERROR_exit("no argument after '%s' :-(",argv[iarg]) ;
       if( !isdigit(argv[iarg][5]) ) ERROR_exit("illegal format for '%s' :-(",argv[iarg]) ;
       nn = (int)strtod(argv[iarg]+5,NULL) ;
       if( nn <= 0 || nn > NWMAX )
         ERROR_exit("illegal warp index in '%s' :-(",argv[iarg]) ;
       if( cwarp[nn-1] != NULL )
         ERROR_exit("'%s': you can't specify warp #%d more than once :-(",argv[iarg],nn) ;
       cwarp[nn-1] = strdup(argv[++iarg]) ;
       if( nn > nwtop ) nwtop = nn ;
       iarg++ ; continue ;
     }

     /*---------------*/

     ERROR_message("Confusingly Unknown option '%s' :-(",argv[iarg]) ;
     suggest_best_prog_option(argv[0],argv[iarg]) ;
     exit(1) ;

   }

   /*-- load any warps left on the command line, after options --*/

   for( ; iarg < argc && nwtop < NWMAX-1 ; iarg++ )
     cwarp[nwtop++] = strdup(argv[iarg]) ;

   /*-- check if all warp strings are affine matrices --*/

#undef  AFFINE_WARP_STRING
#define AFFINE_WARP_STRING(ss)     \
  ( strstr((ss)," ") == NULL &&    \
    ( strcasestr((ss),".1D") != NULL || strcasestr((ss),".txt") != NULL ) )

   for( ntot=ii=0 ; ii < nwtop ; ii++ ){
     if( cwarp[ii] == NULL ) continue ;
     ntot += strlen(cwarp[ii]) ;
     if( ! AFFINE_WARP_STRING(cwarp[ii]) ) break ;  /* not affine */
   }
   if( ntot == 0 ) ERROR_exit("No warps on command line?!") ;

   if( ii == nwtop ){  /* all are affine (this is for Ziad) */
     char *fname = malloc(sizeof(char)*(strlen(prefix)+16)) ; FILE *fp ;
     float a11,a12,a13,a14,a21,a22,a23,a24,a31,a32,a33,a34 ;

     LOAD_IDENT_MAT44(wmat) ;
     for( ii=0 ; ii < nwtop ; ii++ ){
       if( cwarp[ii] == NULL ) continue ;
       smat = CW_read_affine_warp_OLD(cwarp[ii]) ;
       qmat = MAT44_MUL(smat,wmat) ; wmat = qmat ;
     }

     if( strcmp(prefix,"-") == 0 || strncmp(prefix,"stdout",6) == 0 ){
       fp = stdout ; strcpy(fname,"stdout") ;
     } else {
       strcpy(fname,prefix) ;
       if( strstr(fname,".1D") == NULL ) strcat(fname,".aff12.1D") ;
       fp = fopen(fname,"w") ;
       if( fp == NULL ) ERROR_exit("Can't open output matrix file %s",fname) ;
     }
     if( do_iwarp ){
       qmat = MAT44_INV(wmat) ; wmat = qmat ;
     }
     UNLOAD_MAT44(wmat,a11,a12,a13,a14,a21,a22,a23,a24,a31,a32,a33,a34) ;
     fprintf(fp,
             " %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g\n",
             a11,a12,a13,a14,a21,a22,a23,a24,a31,a32,a33,a34 ) ;
     if( verb && fp != stdout ) INFO_message("Wrote matrix to %s",fname) ;
     if( fp != stdout ) fclose(fp) ;
     exit(0) ;
   }

   /*** at least one nonlinear warp ==> cat all strings, use library function to read ***/

   cwarp_all = (char *)calloc(sizeof(char),(ntot+NWMAX)*2) ;
   for( ii=0 ; ii < nwtop ; ii++ ){
     if( cwarp[ii] != NULL ){ strcat(cwarp_all,cwarp[ii]) ; strcat(cwarp_all," ") ; }
   }

   oset = IW3D_read_catenated_warp( cwarp_all ) ;  /* process all of them at once */

   if( do_iwarp ){            /* 18 Jul 2014 */
     THD_3dim_dataset *qwarp ;
     if( verb ) fprintf(stderr,"Applying -iwarp option") ;
     qwarp = THD_nwarp_invert(oset) ;
     DSET_delete(oset) ;
     oset = qwarp ;
     if( verb ) fprintf(stderr,"\n") ;
   }
   tross_Make_History( "3dNwarpCat" , argc,argv , oset ) ;
   if( sname != NULL ) MCW_strncpy( oset->atlas_space , sname , THD_MAX_NAME ) ;
   EDIT_dset_items( oset , ADN_prefix,prefix , ADN_none ) ;
   DSET_write(oset) ; WROTE_DSET(oset) ;

   /*--- run away screaming into the night, never to be seen again ---*/

   INFO_message("total CPU time = %.1f sec  Elapsed = %.1f\n",
                COX_cpu_time() , COX_clock_time() ) ;

   exit(0) ;
}
Exemple #25
0
char * RENAME_main( PLUGIN_interface * plint )
{
   char * new_prefix ;
   MCW_idcode * idc ;
   THD_3dim_dataset * dset ;
   char * old_header_name , * old_brick_name ;
   THD_slist_find find ;
   THD_session * ss ;
   int iss , id , ivv , ierr , mm ;

   /*--------------------------------------------------------------------*/
   /*----- Check inputs from AFNI to see if they are reasonable-ish -----*/

   if( plint == NULL )
      return "***********************\n"
             "RENAME_main: NULL input\n"
             "***********************"  ;

   PLUTO_next_option(plint) ;
   idc  = PLUTO_get_idcode(plint) ;
   dset = PLUTO_find_dset(idc) ;
   if( dset == NULL )
      return "******************************\n"
             "RENAME_main:bad input dataset\n"
             "******************************"  ;

   PLUTO_next_option(plint) ;
   new_prefix = PLUTO_get_string(plint) ;
   if( ! PLUTO_prefix_ok(new_prefix) )
      return "***********************\n"
             "RENAME_main:bad prefix\n"
             "***********************"  ;

   /*------------------------------------------------------*/
   /*---------- At this point, the inputs are OK ----------*/

   /*-- find this dataset in the AFNI library --*/

   find = THD_dset_in_sessionlist( FIND_IDCODE, idc, GLOBAL_library.sslist, -1 ) ;
   iss  = find.sess_index ;
   ss   = GLOBAL_library.sslist->ssar[iss] ;
   id = find.dset_index ; 

   /*-- for each element of this row,
        change its internal names and, if needed, filenames on disk --*/

   ierr = 0 ;

   for( ivv=FIRST_VIEW_TYPE ; ivv <= LAST_VIEW_TYPE ; ivv++ ){

      dset = GET_SESSION_DSET(ss, id, ivv);
      
      if( ! ISVALID_3DIM_DATASET(dset) ) continue ;  /* skip this one */

      /*-- copy the old filenames --*/

      old_header_name = XtNewString( dset->dblk->diskptr->header_name ) ;
      old_brick_name  = XtNewString( dset->dblk->diskptr->brick_name  ) ;

      /*-- initialize the new filenames inside the dataset --*/

      EDIT_dset_items( dset , ADN_prefix , new_prefix , ADN_none ) ;

      /*-- rename the old files to the new files, if they exist on disk --*/

      if( THD_is_file(old_header_name) )
         ierr += rename( old_header_name , dset->dblk->diskptr->header_name ) ;

      /* May 1998: fix .BRIK rename to allow for compression */
#if 0
      if( THD_is_file(old_brick_name) )
         ierr += rename( old_brick_name , dset->dblk->diskptr->brick_name ) ;
#else
      mm = COMPRESS_filecode(old_brick_name) ;
      if( mm != COMPRESS_NOFILE ){
        char * old_name = COMPRESS_add_suffix(old_brick_name,mm) ;
        char * new_name = COMPRESS_add_suffix(dset->dblk->diskptr->brick_name,mm) ;
        ierr += rename( old_name , new_name ) ;
        free(old_name) ; free(new_name) ;
      }
#endif

      XtFree(old_header_name) ; XtFree(old_brick_name) ;
   }

   /*-- clean up AFNI --*/

   PLUTO_fixup_names() ;

   /*-- done --*/

   if( ierr ) return "***********************************************\n"
                     "RENAME_main: some file rename operations failed\n"
                     "***********************************************"  ;

   return NULL ;
}
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *inset=NULL , *outset=NULL ;
   MCW_cluster *nbhd=NULL ;
   byte *mask=NULL ; int mask_nx,mask_ny,mask_nz , automask=0 ;
   char *prefix="./LocalCormat" ;
   int iarg=1 , verb=1 , ntype=0 , kk,nx,ny,nz,nxy,nxyz,nt , xx,yy,zz, vstep ;
   float na,nb,nc , dx,dy,dz ;
   MRI_IMARR *imar=NULL ; MRI_IMAGE *pim=NULL ;
   int mmlag=10 , ii,jj , do_arma=0 , nvout ;
   MRI_IMAGE *concim=NULL ; float *concar=NULL ;

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
     printf(
       "Usage: 3dLocalCORMAT [options] inputdataset\n"
       "\n"
       "Compute the correlation matrix (in time) of the input dataset,\n"
       "up to lag given by -maxlag.  The matrix is averaged over the\n"
       "neighborhood specified by the -nbhd option, and then the entries\n"
       "are output at each voxel in a new dataset.\n"
       "\n"
       "Normally, the input to this program would be the -errts output\n"
       "from 3dDeconvolve, or the equivalent residuals from some other\n"
       "analysis.  If you input a non-residual time series file, you at\n"
       "least should use an appropriate -polort level for detrending!\n"
       "\n"
       "Options:\n"
       "  -input inputdataset\n"
       "  -prefix ppp\n"
       "  -mask mset    {these 2 options are}\n"
       "  -automask     {mutually exclusive.}\n"
       "  -nbhd nnn     [e.g., 'SPHERE(9)' for 9 mm radius]\n"
       "  -polort ppp   [default = 0, which is reasonable for -errts output]\n"
       "  -concat ccc   [as in 3dDeconvolve]\n"
       "  -maxlag mmm   [default = 10]\n"
       "  -ARMA         [estimate ARMA(1,1) parameters into last 2 sub-bricks]\n"
       "\n"
       "A quick hack for my own benignant purposes -- RWCox -- June 2008\n"
     ) ;
     PRINT_COMPILE_DATE ; exit(0) ;
   }

   /*---- official startup ---*/

   PRINT_VERSION("3dLocalCormat"); mainENTRY("3dLocalCormat main"); machdep();
   AFNI_logger("3dLocalCormat",argc,argv); AUTHOR("Zhark the Toeplitzer");

   /*---- loop over options ----*/

   while( iarg < argc && argv[iarg][0] == '-' ){

#if 0
fprintf(stderr,"argv[%d] = %s\n",iarg,argv[iarg]) ;
#endif

     if( strcmp(argv[iarg],"-ARMA") == 0 ){
       do_arma = 1 ; iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-polort") == 0 ){
       char *cpt ;
       if( ++iarg >= argc )
         ERROR_exit("Need argument after option %s",argv[iarg-1]) ;
       pport = (int)strtod(argv[iarg],&cpt) ;
       if( *cpt != '\0' )
         WARNING_message("Illegal non-numeric value after -polort") ;
       if( pport > 3 ){
         pport = 3 ; WARNING_message("-polort set to 3 == max implemented") ;
       } else if( pport < 0 ){
         pport = 0 ; WARNING_message("-polort set to 0 == min implemented") ;
       }
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-input") == 0 ){
       if( inset != NULL  ) ERROR_exit("Can't have two -input options") ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-input'") ;
       inset = THD_open_dataset( argv[iarg] ) ;
       CHECK_OPEN_ERROR(inset,argv[iarg]) ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-prefix") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-prefix'") ;
       prefix = strdup(argv[iarg]) ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-mask") == 0 ){
       THD_3dim_dataset *mset ; int mmm ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask'") ;
       if( mask != NULL || automask ) ERROR_exit("Can't have two mask inputs") ;
       mset = THD_open_dataset( argv[iarg] ) ;
       CHECK_OPEN_ERROR(mset,argv[iarg]) ;
       DSET_load(mset) ; CHECK_LOAD_ERROR(mset) ;
       mask_nx = DSET_NX(mset); mask_ny = DSET_NY(mset); mask_nz = DSET_NZ(mset);
       mask = THD_makemask( mset , 0 , 0.5f, 0.0f ) ; DSET_delete(mset) ;
       if( mask == NULL ) ERROR_exit("Can't make mask from dataset '%s'",argv[iarg]) ;
       mmm = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ;
       INFO_message("Number of voxels in mask = %d",mmm) ;
       if( mmm < 2 ) ERROR_exit("Mask is too small to process") ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-automask") == 0 ){
       if( mask != NULL ) ERROR_exit("Can't have -automask and -mask") ;
       automask = 1 ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-nbhd") == 0 ){
       char *cpt ;
       if( ntype  >  0    ) ERROR_exit("Can't have 2 '-nbhd' options") ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-nbhd'") ;

       cpt = argv[iarg] ;
       if( strncasecmp(cpt,"SPHERE",6) == 0 ){
         sscanf( cpt+7 , "%f" , &na ) ;
         if( na == 0.0f ) ERROR_exit("Can't have a SPHERE of radius 0") ;
         ntype = NTYPE_SPHERE ;
       } else if( strncasecmp(cpt,"RECT",4) == 0 ){
         sscanf( cpt+5 , "%f,%f,%f" , &na,&nb,&nc ) ;
         if( na == 0.0f && nb == 0.0f && nc == 0.0f )
           ERROR_exit("'RECT(0,0,0)' is not a legal neighborhood") ;
         ntype = NTYPE_RECT ;
       } else if( strncasecmp(cpt,"RHDD",4) == 0 ){
         sscanf( cpt+5 , "%f" , &na ) ;
         if( na == 0.0f ) ERROR_exit("Can't have a RHDD of radius 0") ;
         ntype = NTYPE_RHDD ;
       } else {
          ERROR_exit("Unknown -nbhd shape: '%s'",cpt) ;
       }
       iarg++ ; continue ;
     }
       
     if( strcmp(argv[iarg],"-maxlag") == 0 ){
       if( ++iarg >= argc )
         ERROR_exit("Need argument after option %s",argv[iarg-1]) ;
       mmlag = (int)strtod(argv[iarg],NULL) ;
       iarg++ ; continue ;
     }   

     if( strcmp(argv[iarg],"-concat") == 0 ){
       if( concim != NULL )
         ERROR_exit("Can't have two %s options!",argv[iarg]) ;
       if( ++iarg >= argc )
         ERROR_exit("Need argument after option %s",argv[iarg-1]) ;
       concim = mri_read_1D( argv[iarg] ) ;
       if( concim == NULL )
         ERROR_exit("Can't read -concat file '%s'",argv[iarg]) ;
       if( concim->nx < 2 )
         ERROR_exit("-concat file '%s' must have at least 2 entries!",
                    argv[iarg]) ;
       concar = MRI_FLOAT_PTR(concim) ;
       for( ii=1 ; ii < concim->nx ; ii++ )
         if( (int)concar[ii-1] >= (int)concar[ii] )
           ERROR_exit("-concat file '%s' is not ordered increasingly!",
                      argv[iarg]) ;
       iarg++ ; continue ;
     }

     ERROR_exit("Unknown option '%s'",argv[iarg]) ;

   } /*--- end of loop over options ---*/

   if( do_arma && mmlag > 0 && mmlag < 5 )
     ERROR_exit("Can't do -ARMA with -maxlag %d",mmlag) ;

   /*---- deal with input dataset ----*/

   if( inset == NULL ){
     if( iarg >= argc ) ERROR_exit("No input dataset on command line?") ;
     inset = THD_open_dataset( argv[iarg] ) ;
     CHECK_OPEN_ERROR(inset,argv[iarg]) ;
   }
   ntime = DSET_NVALS(inset) ;
   if( ntime < 9 )
     ERROR_exit("Must have at least 9 values per voxel") ;

   DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ;

   if( mask != NULL ){
     if( mask_nx != DSET_NX(inset) ||
         mask_ny != DSET_NY(inset) ||
         mask_nz != DSET_NZ(inset)   )
       ERROR_exit("-mask dataset grid doesn't match input dataset") ;

   } else if( automask ){
     int mmm ;
     mask = THD_automask( inset ) ;
     if( mask == NULL )
       ERROR_message("Can't create -automask from input dataset?") ;
     mmm = THD_countmask( DSET_NVOX(inset) , mask ) ;
     INFO_message("Number of voxels in automask = %d",mmm) ;
     if( mmm < 2 ) ERROR_exit("Automask is too small to process") ;
   }

   /*-- set up blocks of continuous time data --*/
       
   if( DSET_IS_TCAT(inset) ){
     if( concim != NULL ){
       WARNING_message("Ignoring -concat, since dataset is auto-catenated") ;
       mri_free(concim) ;
     }
     concim = mri_new(inset->tcat_num,1,MRI_float) ;
     concar = MRI_FLOAT_PTR(concim) ;
     concar[0] = 0.0 ;
     for( ii=0 ; ii < inset->tcat_num-1 ; ii++ )
       concar[ii+1] = concar[ii] + inset->tcat_len[ii] ;
   } else if( concim == NULL ){ 
     concim = mri_new(1,1,MRI_float) ;
     concar = MRI_FLOAT_PTR(concim)  ; concar[0] = 0 ;
   }
   nbk = concim->nx ;
   bk  = (int *)malloc(sizeof(int)*(nbk+1)) ;
   for( ii=0 ; ii < nbk ; ii++ ) bk[ii] = (int)concar[ii] ;
   bk[nbk] = ntime ;
   mri_free(concim) ;
   mlag = DSET_NVALS(inset) ;
   for( ii=0 ; ii < nbk ; ii++ ){
     jj = bk[ii+1]-bk[ii] ; if( jj < mlag ) mlag = jj ;
     if( bk[ii] < 0 || jj < 9 )
       ERROR_exit("something is rotten in the dataset run lengths") ;
   }
   mlag-- ;
   if( mmlag > 0 && mlag > mmlag ) mlag = mmlag ;
   else                            INFO_message("Max lag set to %d",mlag) ;

   if( do_arma && mlag < 5 )
     ERROR_exit("Can't do -ARMA with maxlag=%d",mlag) ;

   /*---- create neighborhood (as a cluster) -----*/

   if( ntype <= 0 ){         /* default neighborhood */
     ntype = NTYPE_SPHERE ; na = -1.01f ;
     INFO_message("Using default neighborhood = self + 6 neighbors") ;
   }

   switch( ntype ){
     default:
       ERROR_exit("WTF?  ntype=%d",ntype) ;

     case NTYPE_SPHERE:{
       if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; }
       else           { dx = fabsf(DSET_DX(inset)) ;
                        dy = fabsf(DSET_DY(inset)) ;
                        dz = fabsf(DSET_DZ(inset)) ; }
       nbhd = MCW_spheremask( dx,dy,dz , na ) ;
     }
     break ;

     case NTYPE_RECT:{
       if( na < 0.0f ){ dx = 1.0f; na = -na; } else dx = fabsf(DSET_DX(inset));
       if( nb < 0.0f ){ dy = 1.0f; nb = -nb; } else dy = fabsf(DSET_DY(inset));
       if( nc < 0.0f ){ dz = 1.0f; nc = -nc; } else dz = fabsf(DSET_DZ(inset));
       nbhd = MCW_rectmask( dx,dy,dz , na,nb,nc ) ;
     }
     break ;

     case NTYPE_RHDD:{
       if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; }
       else           { dx = fabsf(DSET_DX(inset)) ;
                        dy = fabsf(DSET_DY(inset)) ;
                        dz = fabsf(DSET_DZ(inset)) ; }
       nbhd = MCW_rhddmask( dx,dy,dz , na ) ;
     }
     break ;
   }
   MCW_radsort_cluster( nbhd , dx,dy,dz ) ;  /* 26 Feb 2008 */

   INFO_message("Neighborhood comprises %d voxels",nbhd->num_pt) ;

   /** create output dataset **/

   outset = EDIT_empty_copy(inset) ;
   nvout  = mlag ; if( do_arma ) nvout += 2 ;
   EDIT_dset_items( outset,
                      ADN_prefix   , prefix,
                      ADN_brick_fac, NULL  ,
                      ADN_nvals    , nvout ,
                      ADN_ntt      , nvout ,
                    ADN_none );
   tross_Copy_History( inset , outset ) ;
   tross_Make_History( "3dLocalCormat" , argc,argv , outset ) ;
   for( kk=0 ; kk < nvout ; kk++ )
     EDIT_substitute_brick( outset , kk , MRI_float , NULL ) ;

   nx = DSET_NX(outset) ;
   ny = DSET_NY(outset) ; nxy  = nx*ny  ;
   nz = DSET_NZ(outset) ; nxyz = nxy*nz ;
   vstep = (verb && nxyz > 999) ? nxyz/50 : 0 ;
   if( vstep ) fprintf(stderr,"++ voxel loop: ") ;

   /** actually do the long long slog through all voxels **/

   for( kk=0 ; kk < nxyz ; kk++ ){
     if( vstep && kk%vstep==vstep-1 ) vstep_print() ;
     if( !INMASK(kk) ) continue ;
     IJK_TO_THREE( kk , xx,yy,zz , nx,nxy ) ;
     imar = THD_get_dset_nbhd_array( inset , mask , xx,yy,zz , nbhd ) ;
     if( imar == NULL ) continue ;
     pim = mri_cormat_vector(imar) ; DESTROY_IMARR(imar) ;
     if( pim == NULL ) continue ;
     THD_insert_series( kk, outset, pim->nx, MRI_float, MRI_FLOAT_PTR(pim), 0 ) ;

     if( do_arma ){  /* estimate ARMA(1,1) params and store those, too */
       float_pair ab ;
       float *aa=DSET_ARRAY(outset,mlag), *bb=DSET_ARRAY(outset,mlag+1) ;
       ab = estimate_arma11( pim->nx , MRI_FLOAT_PTR(pim) ) ;
       aa[kk] = ab.a ; bb[kk] = ab.b ;
     }

     mri_free(pim) ;
   }
   if( vstep ) fprintf(stderr,"\n") ;

   DSET_delete(inset) ;
   DSET_write(outset) ;
   WROTE_DSET(outset) ;

   exit(0) ;
}
Exemple #27
0
int main( int argc , char * argv[] )
{
   int do_norm=0 , qdet=2 , have_freq=0 , do_automask=0 ;
   float dt=0.0f , fbot=0.0f,ftop=999999.9f , blur=0.0f ;
   MRI_IMARR *ortar=NULL ; MRI_IMAGE *ortim=NULL ;
   THD_3dim_dataset **ortset=NULL ; int nortset=0 ;
   THD_3dim_dataset *inset=NULL , *outset=NULL;
   char *prefix="RSFC" ;
   byte *mask=NULL ;
   int mask_nx=0,mask_ny=0,mask_nz=0,nmask , verb=1 , 
		nx,ny,nz,nvox , nfft=0 , kk ;
   float **vec , **ort=NULL ; int nort=0 , vv , nopt , ntime  ;
   MRI_vectim *mrv ;
   float pvrad=0.0f ; int nosat=0 ;
   int do_despike=0 ;

	// @@ non-BP variables
	float fbotALL=0.0f, ftopALL=999999.9f; // do full range version
	int NumDen = 0; // switch for doing numerator or denom
	THD_3dim_dataset *outsetALL=NULL ; 	
	int m, mm;
	float delf; // harmonics
	int ind_low,ind_high,N_ny, ctr;
	float sqnt,nt_fac;
	gsl_fft_real_wavetable *real1, *real2; // GSL stuff
	gsl_fft_real_workspace *work;
	double *series1, *series2;	
	double *xx1,*xx2;
	float numer,denom,val;
	float *alff=NULL,*malff=NULL,*falff=NULL,
         *rsfa=NULL,*mrsfa=NULL,*frsfa=NULL; // values
	float meanALFF=0.0f,meanRSFA=0.0f; // will be for mean in brain region
	THD_3dim_dataset *outsetALFF=NULL;
	THD_3dim_dataset *outsetmALFF=NULL;
	THD_3dim_dataset *outsetfALFF=NULL;
	THD_3dim_dataset *outsetRSFA=NULL;
	THD_3dim_dataset *outsetmRSFA=NULL;
	THD_3dim_dataset *outsetfRSFA=NULL;
	char out_lff[300];
	char out_alff[300];
	char out_malff[300];
	char out_falff[300];
	char out_rsfa[300];
	char out_mrsfa[300];
	char out_frsfa[300];
	char out_unBP[300];
	int SERIES_OUT = 1;
	int UNBP_OUT = 0; 
	int DO_RSFA = 1;
	int BP_LAST = 0; // option for only doing filter to LFFs at very end of proc
	float de_rsfa=0.0f,nu_rsfa=0.0f;
	double pow1=0.0,pow2=0.0;

   /*-- help? --*/

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
		printf(
"\n  Program to calculate common resting state functional connectivity (RSFC)\n"
"  parameters (ALFF, mALFF, fALFF, RSFA, etc.) for resting state time\n"
"  series.  This program is **heavily** based on the existing\n"
"  3dBandPass by RW Cox, with the amendments to calculate RSFC\n"
"  parameters written by PA Taylor (July, 2012).\n"
"  This program is part of FATCAT (Taylor & Saad, 2013) in AFNI. Importantly,\n"
"  its functionality can be included in the `afni_proc.py' processing-script \n"
"  generator; see that program's help file for an example including RSFC\n"
"  and spectral parameter calculation via the `-regress_RSFC' option.\n"
"\n"
"* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"
"\n"
"  All options of 3dBandPass may be used here (with a couple other\n"
"  parameter options, as well): essentially, the motivation of this\n"
"  program is to produce ALFF, etc. values of the actual RSFC time\n"
"  series that you calculate.  Therefore, all the 3dBandPass processing\n"
"  you normally do en route to making your final `resting state time\n"
"  series' is done here to generate your LFFs, from which the\n"
"  amplitudes in the LFF band are calculated at the end.  In order to\n"
"  calculate fALFF, the same initial time series are put through the\n"
"  same processing steps which you have chosen but *without* the\n"
"  bandpass part; the spectrum of this second time series is used to\n"
"  calculate the fALFF denominator.\n"
" \n"
"  For more information about each RSFC parameter, see, e.g.:   \n"
"  ALFF/mALFF -- Zang et al. (2007),\n"
"  fALFF --      Zou et al. (2008),\n"
"  RSFA --       Kannurpatti & Biswal (2008).\n"
"\n"
"* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"
"\n"
" + USAGE: 3dRSFC [options] fbot ftop dataset\n"
"\n"
"* One function of this program is to prepare datasets for input\n"
"   to 3dSetupGroupInCorr.  Other uses are left to your imagination.\n"
"\n"
"* 'dataset' is a 3D+time sequence of volumes\n"
"   ++ This must be a single imaging run -- that is, no discontinuities\n"
"       in time from 3dTcat-ing multiple datasets together.\n"
"\n"
"* fbot = lowest frequency in the passband, in Hz\n"
"   ++ fbot can be 0 if you want to do a lowpass filter only;\n"
"       HOWEVER, the mean and Nyquist freq are always removed.\n"
"\n"
"* ftop = highest frequency in the passband (must be > fbot)\n"
"   ++ if ftop > Nyquist freq, then it's a highpass filter only.\n"
"\n"
"* Set fbot=0 and ftop=99999 to do an 'allpass' filter.\n"
"  ++ Except for removal of the 0 and Nyquist frequencies, that is.\n"
"\n"
"* You cannot construct a 'notch' filter with this program!\n"
"  ++ You could use 3dRSFC followed by 3dcalc to get the same effect.\n"
"  ++ If you are understand what you are doing, that is.\n"
"  ++ Of course, that is the AFNI way -- if you don't want to\n"
"     understand what you are doing, use Some other PrograM, and\n"
"     you can still get Fine StatisticaL maps.\n"
"\n"
"* 3dRSFC will fail if fbot and ftop are too close for comfort.\n"
"  ++ Which means closer than one frequency grid step df,\n"
"     where df = 1 / (nfft * dt) [of course]\n"
"\n"
"* The actual FFT length used will be printed, and may be larger\n"
"   than the input time series length for the sake of efficiency.\n"
"  ++ The program will use a power-of-2, possibly multiplied by\n"
"     a power of 3 and/or 5 (up to and including the 3rd power of\n"
"     each of these: 3, 9, 27, and 5, 25, 125).\n"
"\n"
"* Note that the results of combining 3dDetrend and 3dRSFC will\n"
"   depend on the order in which you run these programs.  That's why\n"
"   3dRSFC has the '-ort' and '-dsort' options, so that the\n"
"   time series filtering can be done properly, in one place.\n"
"\n"
"* The output dataset is stored in float format.\n"
"\n"
"* The order of processing steps is the following (most are optional), and\n"
"  for the LFFs, the bandpass is done between the specified fbot and ftop,\n"
"  while for the `whole spectrum' (i.e., fALFF denominator) the bandpass is:\n"
"  done only to exclude the time series mean and the Nyquist frequency:\n"
" (0) Check time series for initial transients [does not alter data]\n"
" (1) Despiking of each time series\n"
" (2) Removal of a constant+linear+quadratic trend in each time series\n"
" (3) Bandpass of data time series\n"
" (4) Bandpass of -ort time series, then detrending of data\n"
"      with respect to the -ort time series\n"
" (5) Bandpass and de-orting of the -dsort dataset,\n"
"      then detrending of the data with respect to -dsort\n"
" (6) Blurring inside the mask [might be slow]\n"
" (7) Local PV calculation     [WILL be slow!]\n"
" (8) L2 normalization         [will be fast.]\n"
" (9) Calculate spectrum and amplitudes, for RSFC parameters.\n"
"\n"
"* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"
"--------\n"
"OPTIONS:\n"
"--------\n"
" -despike        = Despike each time series before other processing.\n"
"                   ++ Hopefully, you don't actually need to do this,\n"
"                      which is why it is optional.\n"
" -ort f.1D       = Also orthogonalize input to columns in f.1D\n"
"                   ++ Multiple '-ort' options are allowed.\n"
" -dsort fset     = Orthogonalize each voxel to the corresponding\n"
"                    voxel time series in dataset 'fset', which must\n"
"                    have the same spatial and temporal grid structure\n"
"                    as the main input dataset.\n"
"                   ++ At present, only one '-dsort' option is allowed.\n"
" -nodetrend      = Skip the quadratic detrending of the input that\n"
"                    occurs before the FFT-based bandpassing.\n"
"                   ++ You would only want to do this if the dataset\n"
"                      had been detrended already in some other program.\n"
" -dt dd          = set time step to 'dd' sec [default=from dataset header]\n"
" -nfft N         = set the FFT length to 'N' [must be a legal value]\n"
" -norm           = Make all output time series have L2 norm = 1\n"
"                   ++ i.e., sum of squares = 1\n"
" -mask mset      = Mask dataset\n"
" -automask       = Create a mask from the input dataset\n"
" -blur fff       = Blur (inside the mask only) with a filter\n"
"                    width (FWHM) of 'fff' millimeters.\n"
" -localPV rrr    = Replace each vector by the local Principal Vector\n"
"                    (AKA first singular vector) from a neighborhood\n"
"                    of radius 'rrr' millimiters.\n"
"                   ++ Note that the PV time series is L2 normalized.\n"
"                   ++ This option is mostly for Bob Cox to have fun with.\n"
"\n"
" -input dataset  = Alternative way to specify input dataset.\n"
" -band fbot ftop = Alternative way to specify passband frequencies.\n"
"\n"
" -prefix ppp     = Set prefix name of output dataset. Name of filtered time\n"
"                   series would be, e.g., ppp_LFF+orig.*, and the parameter\n"
"                   outputs are named with obvious suffices.\n"
" -quiet          = Turn off the fun and informative messages. (Why?)\n"
" -no_rs_out      = Don't output processed time series-- just output\n"
"                   parameters (not recommended, since the point of\n"
"                   calculating RSFC params here is to have them be quite\n"
"                   related to the time series themselves which are used for\n"
"                   further analysis)."
" -un_bp_out      = Output the un-bandpassed series as well (default is not \n"
"                   to).  Name would be, e.g., ppp_unBP+orig.* .\n"
"                   with suffix `_unBP'.\n"
" -no_rsfa        = If you don't want RSFA output (default is to do so).\n"
" -bp_at_end      = A (probably unnecessary) switch to have bandpassing be \n"
"                   the very last processing step that is done in the\n"
"                   sequence of steps listed above; at Step 3 above, only \n"
"                   the time series mean and nyquist are BP'ed out, and then\n"
"                   the LFF series is created only after Step 9.  NB: this \n"
"                   probably makes only very small changes for most\n"
"                   processing sequences (but maybe not, depending usage).\n"
"\n"
" -notrans        = Don't check for initial positive transients in the data:\n"
"  *OR*             ++ The test is a little slow, so skipping it is OK,\n"
" -nosat               if you KNOW the data time series are transient-free.\n"
"                   ++ Or set AFNI_SKIP_SATCHECK to YES.\n"
"                   ++ Initial transients won't be handled well by the\n"
"                      bandpassing algorithm, and in addition may seriously\n"
"                      contaminate any further processing, such as inter-\n"
"                      voxel correlations via InstaCorr.\n"
"                   ++ No other tests are made [yet] for non-stationary \n"
"                      behavior in the time series data.\n"
"\n"
"* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"
"\n"
"  If you use this program, please reference the introductory/description\n"
"  paper for the FATCAT toolbox:\n"
"        Taylor PA, Saad ZS (2013).  FATCAT: (An Efficient) Functional\n"
"        And Tractographic Connectivity Analysis Toolbox. Brain \n"
"        Connectivity 3(5):523-535.\n"
"____________________________________________________________________________\n"
);
		PRINT_AFNI_OMP_USAGE(
" 3dRSFC" ,
" * At present, the only part of 3dRSFC that is parallelized is the\n"
"   '-blur' option, which processes each sub-brick independently.\n"
									) ;
		PRINT_COMPILE_DATE ; exit(0) ;
   }
	
   /*-- startup --*/
	
   mainENTRY("3dRSFC"); machdep();
   AFNI_logger("3dRSFC",argc,argv);
   PRINT_VERSION("3dRSFC (from 3dBandpass by RW Cox): version THETA"); 
	AUTHOR("PA Taylor");
	
   nosat =  AFNI_yesenv("AFNI_SKIP_SATCHECK") ;
	
   nopt = 1 ;
   while( nopt < argc && argv[nopt][0] == '-' ){

		if( strcmp(argv[nopt],"-despike") == 0 ){  /* 08 Oct 2010 */
			do_despike++ ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-nfft") == 0 ){
			int nnup ;
			if( ++nopt >= argc ) ERROR_exit("need an argument after -nfft!") ;
			nfft = (int)strtod(argv[nopt],NULL) ;
			nnup = csfft_nextup_even(nfft) ;
			if( nfft < 16 || nfft != nnup )
				ERROR_exit("value %d after -nfft is illegal! Next legal value = %d",nfft,nnup) ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-blur") == 0 ){
			if( ++nopt >= argc ) ERROR_exit("need an argument after -blur!") ;
			blur = strtod(argv[nopt],NULL) ;
			if( blur <= 0.0f ) WARNING_message("non-positive blur?!") ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-localPV") == 0 ){
			if( ++nopt >= argc ) ERROR_exit("need an argument after -localpv!") ;
			pvrad = strtod(argv[nopt],NULL) ;
			if( pvrad <= 0.0f ) WARNING_message("non-positive -localpv?!") ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-prefix") == 0 ){
			if( ++nopt >= argc ) ERROR_exit("need an argument after -prefix!") ;
			prefix = strdup(argv[nopt]) ;
			if( !THD_filename_ok(prefix) ) ERROR_exit("bad -prefix option!") ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-automask") == 0 ){
			if( mask != NULL ) ERROR_exit("Can't use -mask AND -automask!") ;
			do_automask = 1 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-mask") == 0 ){
			THD_3dim_dataset *mset ;
			if( ++nopt >= argc ) ERROR_exit("Need argument after '-mask'") ;
			if( mask != NULL || do_automask ) ERROR_exit("Can't have two mask inputs") ;
			mset = THD_open_dataset( argv[nopt] ) ;
			CHECK_OPEN_ERROR(mset,argv[nopt]) ;
			DSET_load(mset) ; CHECK_LOAD_ERROR(mset) ;
			mask_nx = DSET_NX(mset); mask_ny = DSET_NY(mset); mask_nz = DSET_NZ(mset);
			mask = THD_makemask( mset , 0 , 0.5f, 0.0f ) ; DSET_delete(mset) ;
			if( mask == NULL ) ERROR_exit("Can't make mask from dataset '%s'",argv[nopt]) ;
			nmask = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ;
			if( verb ) INFO_message("Number of voxels in mask = %d",nmask) ;
			if( nmask < 1 ) ERROR_exit("Mask is too small to process") ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-norm") == 0 ){
			do_norm = 1 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-quiet") == 0 ){
			verb = 0 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-no_rs_out") == 0 ){ // @@
			SERIES_OUT = 0 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-un_bp_out") == 0 ){ // @@
			UNBP_OUT = 1 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-no_rsfa") == 0 ){ // @@
			DO_RSFA = 0 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-bp_at_end") == 0 ){ // @@
			BP_LAST = 1 ; nopt++ ; continue ;
		}




		if( strcmp(argv[nopt],"-notrans") == 0 || strcmp(argv[nopt],"-nosat") == 0 ){
			nosat = 1 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-ort") == 0 ){
			if( ++nopt >= argc ) ERROR_exit("need an argument after -ort!") ;
			if( ortar == NULL ) INIT_IMARR(ortar) ;
			ortim = mri_read_1D( argv[nopt] ) ;
			if( ortim == NULL ) ERROR_exit("can't read from -ort '%s'",argv[nopt]) ;
			mri_add_name(argv[nopt],ortim) ;
			ADDTO_IMARR(ortar,ortim) ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-dsort") == 0 ){
			THD_3dim_dataset *qset ;
			if( ++nopt >= argc ) ERROR_exit("need an argument after -dsort!") ;
			if( nortset > 0 ) ERROR_exit("only 1 -dsort option is allowed!") ;
			qset = THD_open_dataset(argv[nopt]) ;
			CHECK_OPEN_ERROR(qset,argv[nopt]) ;
			ortset = (THD_3dim_dataset **)realloc(ortset,
															  sizeof(THD_3dim_dataset *)*(nortset+1)) ;
			ortset[nortset++] = qset ;
			nopt++ ; continue ;
		}

		if( strncmp(argv[nopt],"-nodetrend",6) == 0 ){
			qdet = 0 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-dt") == 0 ){
			if( ++nopt >= argc ) ERROR_exit("need an argument after -dt!") ;
			dt = (float)strtod(argv[nopt],NULL) ;
			if( dt <= 0.0f ) WARNING_message("value after -dt illegal!") ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-input") == 0 ){
			if( inset != NULL ) ERROR_exit("Can't have 2 -input options!") ;
			if( ++nopt >= argc ) ERROR_exit("need an argument after -input!") ;
			inset = THD_open_dataset(argv[nopt]) ;
			CHECK_OPEN_ERROR(inset,argv[nopt]) ; 

			nopt++ ; continue ;
		}

		if( strncmp(argv[nopt],"-band",5) == 0 ){
			if( ++nopt >= argc-1 ) ERROR_exit("need 2 arguments after -band!") ;
			if( have_freq ) WARNING_message("second -band option replaces first one!") ;
			fbot = strtod(argv[nopt++],NULL) ;
			ftop = strtod(argv[nopt++],NULL) ;
			have_freq = 1 ; continue ;
		}

		ERROR_exit("Unknown option: '%s'",argv[nopt]) ;
   }

   /** check inputs for reasonablositiness **/

   if( !have_freq ){
		if( nopt+1 >= argc )
			ERROR_exit("Need frequencies on command line after options!") ;
		fbot = (float)strtod(argv[nopt++],NULL) ;
		ftop = (float)strtod(argv[nopt++],NULL) ;
   }

   if( inset == NULL ){
		if( nopt >= argc )
			ERROR_exit("Need input dataset name on command line after options!") ;
		inset = THD_open_dataset(argv[nopt]) ;
		CHECK_OPEN_ERROR(inset,argv[nopt]) ;	 

		nopt++ ;
   }
   DSET_UNMSEC(inset) ;

   if( fbot < 0.0f  ) ERROR_exit("fbot value can't be negative!") ;
   if( ftop <= fbot ) ERROR_exit("ftop value %g must be greater than fbot value %g!",ftop,fbot) ;

   ntime = DSET_NVALS(inset) ;
   if( ntime < 9 ) ERROR_exit("Input dataset is too short!") ;

   if( nfft <= 0 ){
		nfft = csfft_nextup_even(ntime) ;
		if( verb ) INFO_message("Data length = %d  FFT length = %d",ntime,nfft) ;
		(void)THD_bandpass_set_nfft(nfft) ;
   } else if( nfft < ntime ){
		ERROR_exit("-nfft %d is less than data length = %d",nfft,ntime) ;
   } else {
		kk = THD_bandpass_set_nfft(nfft) ;
		if( kk != nfft && verb )
			INFO_message("Data length = %d  FFT length = %d",ntime,kk) ;
   }

   if( dt <= 0.0f ){
		dt = DSET_TR(inset) ;
		if( dt <= 0.0f ){
			WARNING_message("Setting dt=1.0 since input dataset lacks a time axis!") ;
			dt = 1.0f ;
		}
   }
   ftopALL = 1./dt ;// Aug,2016: should solve problem of a too-large
                    // value for THD_bandpass_vectors(), while still
                    // being >f_{Nyquist}

   if( !THD_bandpass_OK(ntime,dt,fbot,ftop,1) ) ERROR_exit("Can't continue!") ;

   nx = DSET_NX(inset); ny = DSET_NY(inset); nz = DSET_NZ(inset); nvox = nx*ny*nz;

   /* check mask, or create it */

   if( verb ) INFO_message("Loading input dataset time series" ) ;
   DSET_load(inset) ;

   if( mask != NULL ){
		if( mask_nx != nx || mask_ny != ny || mask_nz != nz )
			ERROR_exit("-mask dataset grid doesn't match input dataset") ;

   } else if( do_automask ){
		mask = THD_automask( inset ) ;
		if( mask == NULL )
			ERROR_message("Can't create -automask from input dataset?") ;
		nmask = THD_countmask( DSET_NVOX(inset) , mask ) ;
		if( verb ) INFO_message("Number of voxels in automask = %d",nmask);
		if( nmask < 1 ) ERROR_exit("Automask is too small to process") ;

   } else {
		mask = (byte *)malloc(sizeof(byte)*nvox) ; nmask = nvox ;
		memset(mask,1,sizeof(byte)*nvox) ;
		// if( verb ) // @@ alert if aaaalllllll vox are going to be analyzed!
		INFO_message("No mask ==> processing all %d voxels",nvox);
   }

   /* A simple check of dataset quality [08 Feb 2010] */

   if( !nosat ){
		float val ;
		INFO_message(
						 "Checking dataset for initial transients [use '-notrans' to skip this test]") ;
		val = THD_saturation_check(inset,mask,0,0) ; kk = (int)(val+0.54321f) ;
		if( kk > 0 )
			ININFO_message(
								"Looks like there %s %d non-steady-state initial time point%s :-(" ,
								((kk==1) ? "is" : "are") , kk , ((kk==1) ? " " : "s") ) ;
		else if( val > 0.3210f )  /* don't ask where this threshold comes from! */
			ININFO_message(
								"MAYBE there's an initial positive transient of 1 point, but it's hard to tell\n") ;
		else
			ININFO_message("No widespread initial positive transient detected :-)") ;
   }

   /* check -dsort inputs for match to inset */

   for( kk=0 ; kk < nortset ; kk++ ){
		if( DSET_NX(ortset[kk])    != nx ||
			 DSET_NY(ortset[kk])    != ny ||
			 DSET_NZ(ortset[kk])    != nz ||
			 DSET_NVALS(ortset[kk]) != ntime )
			ERROR_exit("-dsort %s doesn't match input dataset grid" ,
						  DSET_BRIKNAME(ortset[kk]) ) ;
   }

   /* convert input dataset to a vectim, which is more fun */

	// @@ convert BP'ing ftop/bot into indices for the DFT (below)
	delf = 1.0/(ntime*dt); 
	ind_low = (int) rint(fbot/delf);
	ind_high = (int) rint(ftop/delf);
	if( ntime % 2 ) // nyquist number
		N_ny = (ntime-1)/2;
	else
		N_ny = ntime/2;
	sqnt = sqrt(ntime);
	nt_fac = sqrt(ntime*(ntime-1));

	// @@ if BP_LAST==0:
	// now we go through twice, doing LFF bandpass for NumDen==0 and
	// `full spectrum' processing for NumDen==1.
	// if BP_LAST==1:
	// now we go through once, doing only `full spectrum' processing
	for( NumDen=0 ; NumDen<2 ; NumDen++) {
		//if( NumDen==1 ){ // full spectrum
		//	fbot = fbotALL;
		//	ftop = ftopALL;
		//}
		
		// essentially, just doesn't BP here, and the perfect filtering at end
		// is used for both still; this makes the final output spectrum
		// contain only frequencies in range of 0.01-0.08
		if( BP_LAST==1 )
			INFO_message("Only doing filtering to LFFs at end!");
		
		
		mrv = THD_dset_to_vectim( inset , mask , 0 ) ;
		if( mrv == NULL ) ERROR_exit("Can't load time series data!?") ;
		if( NumDen==1 )
			DSET_unload(inset) ; // @@ only unload on 2nd pass

		/* similarly for the ort vectors */

		if( ortar != NULL ){
			for( kk=0 ; kk < IMARR_COUNT(ortar) ; kk++ ){
				ortim = IMARR_SUBIM(ortar,kk) ;
				if( ortim->nx < ntime )
					ERROR_exit("-ort file %s is shorter than input dataset time series",
								  ortim->name ) ;
				ort  = (float **)realloc( ort , sizeof(float *)*(nort+ortim->ny) ) ;
				for( vv=0 ; vv < ortim->ny ; vv++ )
					ort[nort++] = MRI_FLOAT_PTR(ortim) + ortim->nx * vv ;
			}
		}

		/* all the real work now */

		if( do_despike ){
			int_pair nsp ;
			if( verb ) INFO_message("Testing data time series for spikes") ;
			nsp = THD_vectim_despike9( mrv ) ;
			if( verb ) ININFO_message(" -- Squashed %d spikes from %d voxels",nsp.j,nsp.i) ;
		}

		if( verb ) INFO_message("Bandpassing data time series") ;

		if( (BP_LAST==0) && (NumDen==0) )
			(void)THD_bandpass_vectim( mrv , dt,fbot,ftop , qdet , nort,ort ) ;
		else
			(void)THD_bandpass_vectim( mrv , dt,fbotALL,ftopALL, qdet,nort,ort ) ;

		/* OK, maybe a little more work */

		if( nortset == 1 ){
			MRI_vectim *orv ;
			orv = THD_dset_to_vectim( ortset[0] , mask , 0 ) ;
			if( orv == NULL ){
				ERROR_message("Can't load -dsort %s",DSET_BRIKNAME(ortset[0])) ;
			} else {
				float *dp , *mvv , *ovv , ff ;
				if( verb ) INFO_message("Orthogonalizing to bandpassed -dsort") ;
				//(void)THD_bandpass_vectim( orv , dt,fbot,ftop , qdet , nort,ort ) ; //@@
				if( (BP_LAST==0) && (NumDen==0) )
					(void)THD_bandpass_vectim(orv,dt,fbot,ftop,qdet,nort,ort);
				else
					(void)THD_bandpass_vectim(orv,dt,fbotALL,ftopALL,qdet,nort,ort);

				THD_vectim_normalize( orv ) ;
				dp = malloc(sizeof(float)*mrv->nvec) ;
				THD_vectim_vectim_dot( mrv , orv , dp ) ;
				for( vv=0 ; vv < mrv->nvec ; vv++ ){
					ff = dp[vv] ;
					if( ff != 0.0f ){
						mvv = VECTIM_PTR(mrv,vv) ; ovv = VECTIM_PTR(orv,vv) ;
						for( kk=0 ; kk < ntime ; kk++ ) mvv[kk] -= ff*ovv[kk] ;
					}
				}
				VECTIM_destroy(orv) ; free(dp) ;
			}
		}

		if( blur > 0.0f ){
			if( verb )
				INFO_message("Blurring time series data spatially; FWHM=%.2f",blur) ;
			mri_blur3D_vectim( mrv , blur ) ;
		}
		if( pvrad > 0.0f ){
			if( verb )
				INFO_message("Local PV-ing time series data spatially; radius=%.2f",pvrad) ;
			THD_vectim_normalize( mrv ) ;
			THD_vectim_localpv( mrv , pvrad ) ;
		}
		if( do_norm && pvrad <= 0.0f ){
			if( verb ) INFO_message("L2 normalizing time series data") ;
			THD_vectim_normalize( mrv ) ;
		}

		/* create output dataset, populate it, write it, then quit */
		if( (NumDen==0) ) { // @@ BP'ed version;  will do filt if BP_LAST

			if(BP_LAST) // do bandpass here for BP_LAST
				(void)THD_bandpass_vectim(mrv,dt,fbot,ftop,qdet,0,NULL);

			if( verb ) INFO_message("Creating output dataset in memory, then writing it") ;
			outset = EDIT_empty_copy(inset) ;
			if(SERIES_OUT){
				sprintf(out_lff,"%s_LFF",prefix); 
				EDIT_dset_items( outset , ADN_prefix,out_lff , ADN_none ) ;
				tross_Copy_History( inset , outset ) ;
				tross_Make_History( "3dBandpass" , argc,argv , outset ) ;
			}
			for( vv=0 ; vv < ntime ; vv++ )
				EDIT_substitute_brick( outset , vv , MRI_float , NULL ) ;
		
#if 1
			THD_vectim_to_dset( mrv , outset ) ;
#else
			AFNI_OMP_START ;
#pragma omp parallel
			{ float *far , *var ; int *ivec=mrv->ivec ; int vv,kk ;
#pragma omp for
				for( vv=0 ; vv < ntime ; vv++ ){
					far = DSET_BRICK_ARRAY(outset,vv) ; var = mrv->fvec + vv ;
					for( kk=0 ; kk < nmask ; kk++ ) far[ivec[kk]] = var[kk*ntime] ;
				}
			}
			AFNI_OMP_END ;
#endif
			VECTIM_destroy(mrv) ;
			if(SERIES_OUT){ // @@
				DSET_write(outset) ; if( verb ) WROTE_DSET(outset) ;
			}
		}
		else{ // @@ non-BP'ed version
			if( verb ) INFO_message("Creating output dataset 2 in memory") ;

			// do this here because LFF version was also BP'ed at end.
			if(BP_LAST) // do bandpass here for BP_LAST
				(void)THD_bandpass_vectim(mrv,dt,fbotALL,ftopALL,qdet,0,NULL);

			outsetALL = EDIT_empty_copy(inset) ;
			if(UNBP_OUT){ 
				sprintf(out_unBP,"%s_unBP",prefix); 
				EDIT_dset_items( outsetALL, ADN_prefix, out_unBP, ADN_none );
				tross_Copy_History( inset , outsetALL ) ;
				tross_Make_History( "3dRSFC" , argc,argv , outsetALL ) ;
			}
			for( vv=0 ; vv < ntime ; vv++ )
				EDIT_substitute_brick( outsetALL , vv , MRI_float , NULL ) ;
		
#if 1
			THD_vectim_to_dset( mrv , outsetALL ) ;
#else
			AFNI_OMP_START ;
#pragma omp parallel
			{ float *far , *var ; int *ivec=mrv->ivec ; int vv,kk ;
#pragma omp for
				for( vv=0 ; vv < ntime ; vv++ ){
					far = DSET_BRICK_ARRAY(outsetALL,vv) ; var = mrv->fvec + vv ;
					for( kk=0 ; kk < nmask ; kk++ ) far[ivec[kk]] = var[kk*ntime] ;
				}
			}
			AFNI_OMP_END ;
#endif
			VECTIM_destroy(mrv) ;
			if(UNBP_OUT){ 
				DSET_write(outsetALL) ; if( verb ) WROTE_DSET(outsetALL) ;
			}
		}
	}// end of NumDen loop


	// @@
	INFO_message("Starting the (f)ALaFFel calcs") ;

	// allocations
	series1 = (double *)calloc(ntime,sizeof(double)); 
	series2 = (double *)calloc(ntime,sizeof(double)); 
	xx1 = (double *)calloc(2*ntime,sizeof(double)); 
	xx2 = (double *)calloc(2*ntime,sizeof(double)); 
	alff = (float *)calloc(nvox,sizeof(float)); 
	malff = (float *)calloc(nvox,sizeof(float)); 
	falff = (float *)calloc(nvox,sizeof(float)); 

	if( (series1 == NULL) || (series2 == NULL) 
		 || (xx1 == NULL) || (xx2 == NULL) 
		 || (alff == NULL) || (malff == NULL) || (falff == NULL)) { 
		fprintf(stderr, "\n\n MemAlloc failure.\n\n");
		exit(122);
	}
	if(DO_RSFA) {
		rsfa = (float *)calloc(nvox,sizeof(float)); 
		mrsfa = (float *)calloc(nvox,sizeof(float)); 
		frsfa = (float *)calloc(nvox,sizeof(float)); 
		if( (rsfa == NULL) || (mrsfa == NULL) || (frsfa == NULL)) { 
			fprintf(stderr, "\n\n MemAlloc failure.\n\n");
			exit(123);
		}	
	}
	
	
	work = gsl_fft_real_workspace_alloc (ntime);
	real1 = gsl_fft_real_wavetable_alloc (ntime);
	real2 = gsl_fft_real_wavetable_alloc (ntime);
	gsl_complex_packed_array compl_freqs1 = xx1;
	gsl_complex_packed_array compl_freqs2 = xx2;




	// *********************************************************************
	// *********************************************************************
	// **************    Falafelling = ALFF/fALFF calcs    *****************
	// *********************************************************************
	// *********************************************************************

	// Be now have the BP'ed data set (outset) and the non-BP'ed one
	// (outsetALL).  now we'll FFT both, get amplitudes in appropriate
	// ranges, and calculate:  ALFF, mALFF, fALFF,

	ctr = 0;
	for( kk=0; kk<nvox ; kk++) {
		if(mask[kk]) {
			
			// BP one, and unBP one, either for BP_LAST or !BP_LAST
			for( m=0 ; m<ntime ; m++ ) {
				series1[m] = THD_get_voxel(outset,kk,m);
				series2[m] = THD_get_voxel(outsetALL,kk,m);
			}
			
			
			mm = gsl_fft_real_transform(series1, 1, ntime, real1, work);
			mm = gsl_fft_halfcomplex_unpack(series1, compl_freqs1, 1, ntime);
			mm = gsl_fft_real_transform(series2, 1, ntime, real2, work);
			mm = gsl_fft_halfcomplex_unpack(series2, compl_freqs2, 1, ntime);

			numer = 0.0f; 
			denom = 0.0f;
			de_rsfa = 0.0f;
			nu_rsfa = 0.0f;
			for( m=1 ; m<N_ny ; m++ ) {
				mm = 2*m;
				pow2 = compl_freqs2[mm]*compl_freqs2[mm] +
					compl_freqs2[mm+1]*compl_freqs2[mm+1]; // power
				//pow2*=2;// factor of 2 since ampls are even funcs
				denom+= (float) sqrt(pow2); // amplitude 
				de_rsfa+= (float) pow2;
				
				if( ( m>=ind_low ) && ( m<=ind_high ) ){
					pow1 = compl_freqs1[mm]*compl_freqs1[mm]+
						compl_freqs1[mm+1]*compl_freqs1[mm+1];
					//pow1*=2;
					numer+= (float) sqrt(pow1);
					nu_rsfa+= (float) pow1;
				}
			}

			if( denom>0.000001 )
			  falff[kk] = numer/denom;
			else
			  falff[kk] = 0.;
			alff[kk] = 2*numer/sqnt;// factor of 2 since ampl is even funct
			meanALFF+= alff[kk];

			if(DO_RSFA){
			  nu_rsfa = sqrt(2*nu_rsfa); // factor of 2 since ampls 
			  de_rsfa = sqrt(2*de_rsfa); // are even funcs
			  if( de_rsfa>0.000001 )
			    frsfa[kk] = nu_rsfa/de_rsfa;
			  else
			    frsfa[kk]=0.;
			  rsfa[kk] = nu_rsfa/nt_fac;
			  meanRSFA+= rsfa[kk];
			}
			
			ctr+=1;
		}
	}
	meanALFF/= ctr;
	meanRSFA/= ctr;

	gsl_fft_real_wavetable_free(real1);
	gsl_fft_real_wavetable_free(real2);
	gsl_fft_real_workspace_free(work);

	// ALFFs divided by mean of brain value
	for( kk=0 ; kk<nvox ; kk++ ) 
		if(mask[kk]){
			malff[kk] = alff[kk]/meanALFF;
			if(DO_RSFA)
				mrsfa[kk] = rsfa[kk]/meanRSFA;
		}
	// **************************************************************
	// **************************************************************
	//                 Store and output
	// **************************************************************
	// **************************************************************
	
	outsetALFF = EDIT_empty_copy( inset ) ; 
	sprintf(out_alff,"%s_ALFF",prefix); 
	EDIT_dset_items( outsetALFF,
                    ADN_nvals, 1,
						  ADN_datum_all , MRI_float , 
						  ADN_prefix    , out_alff,
						  ADN_none ) ;
	if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetALFF)) )
		ERROR_exit("Can't overwrite existing dataset '%s'",
					  DSET_HEADNAME(outsetALFF));
	EDIT_substitute_brick(outsetALFF, 0, MRI_float, alff); 
	alff=NULL;
	THD_load_statistics(outsetALFF);
	tross_Make_History("3dRSFC", argc, argv, outsetALFF);
	THD_write_3dim_dataset(NULL, NULL, outsetALFF, True);

	outsetfALFF = EDIT_empty_copy( inset ) ;
	sprintf(out_falff,"%s_fALFF",prefix); 
	EDIT_dset_items( outsetfALFF,
                    ADN_nvals, 1,
						  ADN_datum_all , MRI_float , 
						  ADN_prefix    , out_falff,
						  ADN_none ) ;
	if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetfALFF)) )
		ERROR_exit("Can't overwrite existing dataset '%s'",
					  DSET_HEADNAME(outsetfALFF));
	EDIT_substitute_brick(outsetfALFF, 0, MRI_float, falff); 
	falff=NULL;
	THD_load_statistics(outsetfALFF);
	tross_Make_History("3dRSFC", argc, argv, outsetfALFF);
	THD_write_3dim_dataset(NULL, NULL, outsetfALFF, True);



	outsetmALFF = EDIT_empty_copy( inset ) ;
	sprintf(out_malff,"%s_mALFF",prefix); 
	EDIT_dset_items( outsetmALFF,
                    ADN_nvals, 1,
                    ADN_datum_all , MRI_float , 
						  ADN_prefix    , out_malff,
						  ADN_none ) ;
	if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetmALFF)) )
		ERROR_exit("Can't overwrite existing dataset '%s'",
					  DSET_HEADNAME(outsetmALFF));
	EDIT_substitute_brick(outsetmALFF, 0, MRI_float, malff); 
	malff=NULL;
	THD_load_statistics(outsetmALFF);
	tross_Make_History("3dRSFC", argc, argv, outsetmALFF);
	THD_write_3dim_dataset(NULL, NULL, outsetmALFF, True);

	if(DO_RSFA){
     outsetRSFA = EDIT_empty_copy( inset ) ;
		sprintf(out_rsfa,"%s_RSFA",prefix); 
		EDIT_dset_items( outsetRSFA,
                       ADN_nvals, 1,
                       ADN_datum_all , MRI_float , 
							  ADN_prefix    , out_rsfa,
							  ADN_none ) ;
		if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetRSFA)) )
			ERROR_exit("Can't overwrite existing dataset '%s'",
						  DSET_HEADNAME(outsetRSFA));
		EDIT_substitute_brick(outsetRSFA, 0, MRI_float, rsfa); 
		rsfa=NULL;
		THD_load_statistics(outsetRSFA);
		tross_Make_History("3dRSFC", argc, argv, outsetRSFA);
		THD_write_3dim_dataset(NULL, NULL, outsetRSFA, True);
		
      outsetfRSFA = EDIT_empty_copy( inset ) ;
		sprintf(out_frsfa,"%s_fRSFA",prefix); 
		EDIT_dset_items( outsetfRSFA,
                       ADN_nvals, 1,
                       ADN_datum_all , MRI_float , 
							  ADN_prefix    , out_frsfa,
							  ADN_none ) ;
		if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetfRSFA)) )
			ERROR_exit("Can't overwrite existing dataset '%s'",
						  DSET_HEADNAME(outsetfRSFA));
		EDIT_substitute_brick(outsetfRSFA, 0, MRI_float, frsfa); 
		frsfa=NULL;
		THD_load_statistics(outsetfRSFA);
		tross_Make_History("3dRSFC", argc, argv, outsetfRSFA);
		THD_write_3dim_dataset(NULL, NULL, outsetfRSFA, True);
		
		outsetmRSFA = EDIT_empty_copy( inset ) ; 
		sprintf(out_mrsfa,"%s_mRSFA",prefix); 
		EDIT_dset_items( outsetmRSFA,
                       ADN_nvals, 1,
                       ADN_datum_all , MRI_float , 
							  ADN_prefix    , out_mrsfa,
							  ADN_none ) ;
		if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetmRSFA)) )
			ERROR_exit("Can't overwrite existing dataset '%s'",
						  DSET_HEADNAME(outsetmRSFA));
		EDIT_substitute_brick(outsetmRSFA, 0, MRI_float, mrsfa); 
		mrsfa=NULL;
		THD_load_statistics(outsetmRSFA);
		tross_Make_History("3dRSFC", argc, argv, outsetmRSFA);
		THD_write_3dim_dataset(NULL, NULL, outsetmRSFA, True);
	}



	// ************************************************************
	// ************************************************************
	//                    Freeing
	// ************************************************************
	// ************************************************************

	DSET_delete(inset);
	DSET_delete(outsetALL);
	DSET_delete(outset);
	DSET_delete(outsetALFF);
	DSET_delete(outsetmALFF);
	DSET_delete(outsetfALFF);
	DSET_delete(outsetRSFA);
	DSET_delete(outsetmRSFA);
	DSET_delete(outsetfRSFA);

	free(inset);
	free(outsetALL);
	free(outset);
	free(outsetALFF);
	free(outsetmALFF);
	free(outsetfALFF);
	free(outsetRSFA);
	free(outsetmRSFA);
	free(outsetfRSFA);

	free(rsfa);
	free(mrsfa);
	free(frsfa);
	free(alff);
	free(malff);
	free(falff);
	free(mask);
	free(series1);
	free(series2);
	free(xx1);
	free(xx2);

	exit(0) ;
}
Exemple #28
0
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *xset , *cset, *mset=NULL ;
   int nopt=1 , method=PEARSON , do_autoclip=0 ;
   int nvox , nvals , ii, jj, kout, kin, polort=1 ;
   int ix1,jy1,kz1, ix2, jy2, kz2 ;
   char *prefix = "degree_centrality" ;
   byte *mask=NULL;
   int   nmask , abuc=1 ;
   int   all_source=0;        /* output all source voxels  25 Jun 2010 [rickr] */
   char str[32] , *cpt ;
   int *imap = NULL ; MRI_vectim *xvectim ;
   float (*corfun)(int,float *,float*) = NULL ;
   /* djc - add 1d file output for similarity matrix */
   FILE *fout1D=NULL;

   /* CC - we will have two subbricks: binary and weighted centrality */
   int nsubbriks = 2;
   int subbrik = 0;
   float * bodset;
   float * wodset;

   int nb_ctr = 0;

   /* CC - added flags for thresholding correlations */
   double thresh = 0.0;
   double othresh = 0.0;
   int dothresh = 0;
   double sparsity = 0.0;
   int dosparsity = 0;
  
   /* variables for calculating degree centrality */
   long * binaryDC = NULL;
   double * weightedDC = NULL;

   /* variables for histogram */
   hist_node_head* histogram=NULL;
   hist_node* hptr=NULL;
   hist_node* pptr=NULL;
   int bottom_node_idx = 0;
   int totNumCor = 0;
   long totPosCor = 0;
   int ngoal = 0;
   int nretain = 0;
   float binwidth = 0.0;
   int nhistnodes = 50;

   /*----*/

   AFNI_SETUP_OMP(0) ;  /* 24 Jun 2013 */

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
      printf(
"Usage: 3dDegreeCentrality [options] dset\n"
"  Computes voxelwise weighted and binary degree centrality and\n"
"  stores the result in a new 3D bucket dataset as floats to\n"
"  preserve their values. Degree centrality reflects the strength and\n"
"  extent of the correlation of a voxel with every other voxel in\n"
"  the brain.\n\n"
"  Conceptually the process involves: \n"
"      1. Calculating the correlation between voxel time series for\n"
"         every pair of voxels in the brain (as determined by masking)\n"
"      2. Applying a threshold to the resulting correlations to exclude\n"
"         those that might have arisen by chance, or to sparsify the\n"
"         connectivity graph.\n"
"      3. At each voxel, summarizing its correlation with other voxels\n"
"         in the brain, by either counting the number of voxels correlated\n"
"         with the seed voxel (binary) or by summing the correlation \n"
"         coefficients (weighted).\n"
"   Practically the algorithm is ordered differently to optimize for\n"
"   computational time and memory usage.\n\n"
"   The threshold can be supplied as a correlation coefficient, \n"
"   or a sparsity threshold. The sparsity threshold reflects the fraction\n"
"   of connections that should be retained after the threshold has been\n"
"   applied. To minimize resource consumption, using a sparsity threshold\n"
"   involves a two-step procedure. In the first step, a correlation\n"
"   coefficient threshold is applied to substantially reduce the number\n"
"   of correlations. Next, the remaining correlations are sorted and a\n"
"   threshold is calculated so that only the specified fraction of \n"
"   possible correlations are above threshold. Due to ties between\n"
"   correlations, the fraction of correlations that pass the sparsity\n"
"   threshold might be slightly more than the number specified.\n\n"
"   Regardless of the thresholding procedure employed, negative \n"
"   correlations are excluded from the calculations.\n" 
"\n"
"Options:\n"
"  -pearson  = Correlation is the normal Pearson (product moment)\n"
"               correlation coefficient [default].\n"
   #if 0
"  -spearman = Correlation is the Spearman (rank) correlation\n"
"               coefficient.\n"
"  -quadrant = Correlation is the quadrant correlation coefficient.\n"
   #else
"  -spearman AND -quadrant are disabled at this time :-(\n"
   #endif
"\n"
"  -thresh r = exclude correlations <= r from calculations\n"
"  -sparsity s = only use top s percent of correlations in calculations\n"
"                s should be an integer between 0 and 100. Uses an\n"
"                an adaptive thresholding procedure to reduce memory.\n"
"                The speed of determining the adaptive threshold can\n"
"                be improved by specifying an initial threshold with\n"
"                the -thresh flag.\n"
"\n"
"  -polort m = Remove polynomical trend of order 'm', for m=-1..3.\n"
"               [default is m=1; removal is by least squares].\n"
"               Using m=-1 means no detrending; this is only useful\n"
"               for data/information that has been pre-processed.\n"
"\n"
"  -autoclip = Clip off low-intensity regions in the dataset,\n"
"  -automask =  so that the correlation is only computed between\n"
"               high-intensity (presumably brain) voxels.  The\n"
"               mask is determined the same way that 3dAutomask works.\n"
"\n"
"  -mask mmm = Mask to define 'in-brain' voxels. Reducing the number\n"
"               the number of voxels included in the calculation will\n"
"               significantly speedup the calculation. Consider using\n"
"               a mask to constrain the calculations to the grey matter\n"
"               rather than the whole brain. This is also preferrable\n"
"               to using -autoclip or -automask.\n"
"\n"
"  -prefix p = Save output into dataset with prefix 'p', this file will\n"
"               contain bricks for both 'weighted' or 'degree' centrality\n"
"               [default prefix is 'deg_centrality'].\n"
"\n"
"  -out1D f = Save information about the above threshold correlations to\n"
"              1D file 'f'. Each row of this file will contain:\n"
"               Voxel1 Voxel2 i1 j1 k1 i2 j2 k2 Corr\n"
"              Where voxel1 and voxel2 are the 1D indices of the pair of\n"
"              voxels, i j k correspond to their 3D coordinates, and Corr\n"
"              is the value of the correlation between the voxel time courses.\n" 
"\n"
"Notes:\n"
" * The output dataset is a bucket type of floats.\n"
" * The program prints out an estimate of its memory used\n"
"    when it ends.  It also prints out a progress 'meter'\n"
"    to keep you pacified.\n"
"\n"
"-- RWCox - 31 Jan 2002 and 16 Jul 2010\n"
"-- Cameron Craddock - 26 Sept 2015 \n"
            ) ;
      PRINT_AFNI_OMP_USAGE("3dDegreeCentrality",NULL) ;
      PRINT_COMPILE_DATE ; exit(0) ;
   }

   mainENTRY("3dDegreeCentrality main"); machdep(); PRINT_VERSION("3dDegreeCentrality");
   AFNI_logger("3dDegreeCentrality",argc,argv);

   /*-- option processing --*/

   while( nopt < argc && argv[nopt][0] == '-' ){

      if( strcmp(argv[nopt],"-time") == 0 ){
         abuc = 0 ; nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-autoclip") == 0 ||
          strcmp(argv[nopt],"-automask") == 0   ){

         do_autoclip = 1 ; nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-mask") == 0 ){
         mset = THD_open_dataset(argv[++nopt]);
         CHECK_OPEN_ERROR(mset,argv[nopt]);
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-pearson") == 0 ){
         method = PEARSON ; nopt++ ; continue ;
      }

#if 0
      if( strcmp(argv[nopt],"-spearman") == 0 ){
         method = SPEARMAN ; nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-quadrant") == 0 ){
         method = QUADRANT ; nopt++ ; continue ;
      }
#endif

      if( strcmp(argv[nopt],"-eta2") == 0 ){
         method = ETA2 ; nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-prefix") == 0 ){
         prefix = strdup(argv[++nopt]) ;
         if( !THD_filename_ok(prefix) ){
            ERROR_exit("Illegal value after -prefix!") ;
         }
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-thresh") == 0 ){
         double val = (double)strtod(argv[++nopt],&cpt) ;
         if( *cpt != '\0' || val >= 1.0 || val < 0.0 ){
            ERROR_exit("Illegal value (%f) after -thresh!", val) ;
         }
         dothresh = 1;
         thresh = val ; othresh = val ; nopt++ ; continue ;
      }
      if( strcmp(argv[nopt],"-sparsity") == 0 ){
         double val = (double)strtod(argv[++nopt],&cpt) ;
         if( *cpt != '\0' || val > 100 || val <= 0 ){
            ERROR_exit("Illegal value (%f) after -sparsity!", val) ;
         }
         if( val > 5.0 )
         {
             WARNING_message("Sparsity %3.2f%% is large and will require alot of memory and time, consider using a smaller value. ", val);
         }
         dosparsity = 1 ;
         sparsity = val ; nopt++ ; continue ;
      }
      if( strcmp(argv[nopt],"-polort") == 0 ){
         int val = (int)strtod(argv[++nopt],&cpt) ;
         if( *cpt != '\0' || val < -1 || val > 3 ){
            ERROR_exit("Illegal value after -polort!") ;
         }
         polort = val ; nopt++ ; continue ;
      }
      if( strcmp(argv[nopt],"-mem_stat") == 0 ){
         MEM_STAT = 1 ; nopt++ ; continue ;
      }
      if( strncmp(argv[nopt],"-mem_profile",8) == 0 ){
         MEM_PROF = 1 ; nopt++ ; continue ;
      }
      /* check for 1d argument */
      if ( strcmp(argv[nopt],"-out1D") == 0 ){
          if (!(fout1D = fopen(argv[++nopt], "w"))) {
             ERROR_message("Failed to open %s for writing", argv[nopt]);
             exit(1);
          }
          nopt++ ; continue ;
      }

      ERROR_exit("Illegal option: %s",argv[nopt]) ;
   }

   /*-- open dataset, check for legality --*/

   if( nopt >= argc ) ERROR_exit("Need a dataset on command line!?") ;

   xset = THD_open_dataset(argv[nopt]); CHECK_OPEN_ERROR(xset,argv[nopt]);


   if( DSET_NVALS(xset) < 3 )
     ERROR_exit("Input dataset %s does not have 3 or more sub-bricks!",argv[nopt]) ;
   DSET_load(xset) ; CHECK_LOAD_ERROR(xset) ;

   /*-- compute mask array, if desired --*/
   nvox = DSET_NVOX(xset) ; nvals = DSET_NVALS(xset) ;
   INC_MEM_STATS((nvox * nvals * sizeof(double)), "input dset");
   PRINT_MEM_STATS("inset");

   /* if a mask was specified make sure it is appropriate */
   if( mset ){

      if( DSET_NVOX(mset) != nvox )
         ERROR_exit("Input and mask dataset differ in number of voxels!") ;
      mask  = THD_makemask(mset, 0, 1.0, 0.0) ;

      /* update running memory statistics to reflect loading the image */
      INC_MEM_STATS( mset->dblk->total_bytes, "mask dset" );
      PRINT_MEM_STATS( "mset load" );

      nmask = THD_countmask( nvox , mask ) ;
      INC_MEM_STATS( nmask * sizeof(byte), "mask array" );
      PRINT_MEM_STATS( "mask" );

      INFO_message("%d voxels in -mask dataset",nmask) ;
      if( nmask < 2 ) ERROR_exit("Only %d voxels in -mask, exiting...",nmask);

      /* update running memory statistics to reflect loading the image */
      DEC_MEM_STATS( mset->dblk->total_bytes, "mask dset" );
      DSET_unload(mset) ;
      PRINT_MEM_STATS( "mset unload" );
   } 
   /* if automasking is requested, handle that now */
   else if( do_autoclip ){
      mask  = THD_automask( xset ) ;
      nmask = THD_countmask( nvox , mask ) ;
      INFO_message("%d voxels survive -autoclip",nmask) ;
      if( nmask < 2 ) ERROR_exit("Only %d voxels in -automask!",nmask);
   }
   /* otherwise we use all of the voxels in the image */
   else {
      nmask = nvox ;
      INFO_message("computing for all %d voxels",nmask) ;
   }
   
   if( method == ETA2 && polort >= 0 )
      WARNING_message("Polort for -eta2 should probably be -1...");

    /* djc - 1d file out init */
    if (fout1D != NULL) {
        /* define affine matrix */
        mat44 affine_mat = xset->daxes->ijk_to_dicom;

        /* print command line statement */
        fprintf(fout1D,"#Similarity matrix from command:\n#");
        for(ii=0; ii<argc; ++ii) fprintf(fout1D,"%s ", argv[ii]);

        /* Print affine matrix */
        fprintf(fout1D,"\n");
        fprintf(fout1D,"#[ ");
        int mi, mj;
        for(mi = 0; mi < 4; mi++) {
            for(mj = 0; mj < 4; mj++) {
                fprintf(fout1D, "%.6f ", affine_mat.m[mi][mj]);
            }
        }
        fprintf(fout1D, "]\n");

        /* Print image extents*/
        THD_dataxes *xset_daxes = xset->daxes;
        fprintf(fout1D, "#Image dimensions:\n");
        fprintf(fout1D, "#[%d, %d, %d]\n",
                xset_daxes->nxx, xset_daxes->nyy, xset_daxes->nzz);

        /* Similarity matrix headers */
        fprintf(fout1D,"#Voxel1 Voxel2 i1 j1 k1 i2 j2 k2 Corr\n");
    }


   /* CC calculate the total number of possible correlations, will be 
       usefule down the road */
   totPosCor = (.5*((float)nmask))*((float)(nmask-1));

   /**  For the case of Pearson correlation, we make sure the  **/
   /**  data time series have their mean removed (polort >= 0) **/
   /**  and are normalized, so that correlation = dot product, **/
   /**  and we can use function zm_THD_pearson_corr for speed. **/

   switch( method ){
     default:
     case PEARSON: corfun = zm_THD_pearson_corr ; break ;
     case ETA2:    corfun = my_THD_eta_squared  ; break ;
   }

   /*-- create vectim from input dataset --*/
   INFO_message("vectim-izing input dataset") ;

   /*-- CC added in mask to reduce the size of xvectim -- */
   xvectim = THD_dset_to_vectim( xset , mask , 0 ) ;
   if( xvectim == NULL ) ERROR_exit("Can't create vectim?!") ;

   /*-- CC update our memory stats to reflect vectim -- */
   INC_MEM_STATS((xvectim->nvec*sizeof(int)) +
                       ((xvectim->nvec)*(xvectim->nvals))*sizeof(float) +
                       sizeof(MRI_vectim), "vectim");
   PRINT_MEM_STATS( "vectim" );

   /*--- CC the vectim contains a mapping between voxel index and mask index, 
         tap into that here to avoid duplicating memory usage ---*/

   if( mask != NULL )
   {
       imap = xvectim->ivec;

       /* --- CC free the mask */
       DEC_MEM_STATS( nmask*sizeof(byte), "mask array" );
       free(mask); mask=NULL;
       PRINT_MEM_STATS( "mask unload" );
   }

   /* -- CC unloading the dataset to reduce memory usage ?? -- */
   DEC_MEM_STATS((DSET_NVOX(xset) * DSET_NVALS(xset) * sizeof(double)), "input dset");
   DSET_unload(xset) ;
   PRINT_MEM_STATS("inset unload");

   /* -- CC configure detrending --*/
   if( polort < 0 && method == PEARSON ){
     polort = 0; WARNING_message("Pearson correlation always uses polort >= 0");
   }
   if( polort >= 0 ){
     for( ii=0 ; ii < xvectim->nvec ; ii++ ){  /* remove polynomial trend */
       DETREND_polort(polort,nvals,VECTIM_PTR(xvectim,ii)) ;
     }
   }


   /* -- this procedure does not change time series that have zero variance -- */
   if( method == PEARSON ) THD_vectim_normalize(xvectim) ;  /* L2 norm = 1 */

    /* -- CC create arrays to hold degree and weighted centrality while
          they are being calculated -- */
    if( dosparsity == 0 )
    {
        if( ( binaryDC = (long*)calloc( nmask, sizeof(long) )) == NULL )
        {
            ERROR_message( "Could not allocate %d byte array for binary DC calculation\n",
                nmask*sizeof(long)); 
        }

        /* -- update running memory estimate to reflect memory allocation */ 
        INC_MEM_STATS( nmask*sizeof(long), "binary DC array" );
        PRINT_MEM_STATS( "binaryDC" );

        if( ( weightedDC = (double*)calloc( nmask, sizeof(double) )) == NULL )
        {
            if (binaryDC){ free(binaryDC); binaryDC = NULL; }
            ERROR_message( "Could not allocate %d byte array for weighted DC calculation\n",
                nmask*sizeof(double)); 
        }
        /* -- update running memory estimate to reflect memory allocation */ 
        INC_MEM_STATS( nmask*sizeof(double), "weighted DC array" );
        PRINT_MEM_STATS( "weightedDC" );
    }


    /* -- CC if we are using a sparsity threshold, build a histogram to calculate the 
         threshold */
    if (dosparsity == 1)
    {
        /* make sure that there is a bin for correlation values that == 1.0 */
        binwidth = (1.005-thresh)/nhistnodes;

        /* calculate the number of correlations we wish to retain */
        ngoal = nretain = (int)(((double)totPosCor)*((double)sparsity) / 100.0);

        /* allocate memory for the histogram bins */
        if(( histogram = (hist_node_head*)malloc(nhistnodes*sizeof(hist_node_head))) == NULL )
        {
            /* if the allocation fails, free all memory and exit */
            if (binaryDC){ free(binaryDC); binaryDC = NULL; }
            if (weightedDC){ free(weightedDC); weightedDC = NULL; }
            ERROR_message( "Could not allocate %d byte array for histogram\n",
                nhistnodes*sizeof(hist_node_head)); 
        }
        else {
            /* -- update running memory estimate to reflect memory allocation */ 
            INC_MEM_STATS( nhistnodes*sizeof(hist_node_head), "hist bins" );
            PRINT_MEM_STATS( "hist1" );
        }

        /* initialize history bins */
        for( kout = 0; kout < nhistnodes; kout++ )
        {
            histogram[ kout ].bin_low = thresh+kout*binwidth;
            histogram[ kout ].bin_high = histogram[ kout ].bin_low+binwidth;
            histogram[ kout ].nbin = 0;
            histogram[ kout ].nodes = NULL; 
            /*INFO_message("Hist bin %d [%3.3f, %3.3f) [%d, %p]\n",
                kout, histogram[ kout ].bin_low, histogram[ kout ].bin_high,
                histogram[ kout ].nbin, histogram[ kout ].nodes );*/
        }
    }

    /*-- tell the user what we are about to do --*/
    if (dosparsity == 0 )
    {
        INFO_message( "Calculating degree centrality with threshold = %f.\n", thresh);
    }
    else
    {
        INFO_message( "Calculating degree centrality with threshold = %f and sparsity = %3.2f%% (%d)\n",
            thresh, sparsity, nretain);
    }

    /*---------- loop over mask voxels, correlate ----------*/
    AFNI_OMP_START ;
#pragma omp parallel if( nmask > 999 )
    {
       int lii,ljj,lin,lout,ithr,nthr,vstep,vii ;
       float *xsar , *ysar ;
       hist_node* new_node = NULL ;
       hist_node* tptr = NULL ;
       hist_node* rptr = NULL ;
       int new_node_idx = 0;
       double car = 0.0 ; 

       /*-- get information about who we are --*/
#ifdef USE_OMP
       ithr = omp_get_thread_num() ;
       nthr = omp_get_num_threads() ;
       if( ithr == 0 ) INFO_message("%d OpenMP threads started",nthr) ;
#else
       ithr = 0 ; nthr = 1 ;
#endif

       /*-- For the progress tracker, we want to print out 50 numbers,
            figure out a number of loop iterations that will make this easy */
       vstep = (int)( nmask / (nthr*50.0f) + 0.901f ) ; vii = 0 ;
       if((MEM_STAT==0) && (ithr == 0 )) fprintf(stderr,"Looping:") ;

#pragma omp for schedule(static, 1)
       for( lout=0 ; lout < xvectim->nvec ; lout++ ){  /*----- outer voxel loop -----*/

          if( ithr == 0 && vstep > 2 ) /* allow small dsets 16 Jun 2011 [rickr] */
          { vii++ ; if( vii%vstep == vstep/2 && MEM_STAT == 0 ) vstep_print(); }

          /* get ref time series from this voxel */
          xsar = VECTIM_PTR(xvectim,lout) ;

          /* try to make calculation more efficient by only calculating the unique 
             correlations */
          for( lin=(lout+1) ; lin < xvectim->nvec ; lin++ ){  /*----- inner loop over voxels -----*/

             /* extract the voxel time series */
             ysar = VECTIM_PTR(xvectim,lin) ;

             /* now correlate the time series */
             car = (double)(corfun(nvals,xsar,ysar)) ;

             if ( car <= thresh )
             {
                 continue ;
             }

/* update degree centrality values, hopefully the pragma
   will handle mutual exclusion */
#pragma omp critical(dataupdate)
             {
                 /* if the correlation is less than threshold, ignore it */
                 if ( car > thresh )
                 {
                     totNumCor += 1;
               
                     if ( dosparsity == 0 )
                     { 
                         binaryDC[lout] += 1; binaryDC[lin] += 1;
                         weightedDC[lout] += car; weightedDC[lin] += car;

                         /* print correlation out to the 1D file */
                         if ( fout1D != NULL )
                         {
                             /* determine the i,j,k coords */
                             ix1 = DSET_index_to_ix(xset,lii) ;
                             jy1 = DSET_index_to_jy(xset,lii) ;
                             kz1 = DSET_index_to_kz(xset,lii) ;
                             ix2 = DSET_index_to_ix(xset,ljj) ;
                             jy2 = DSET_index_to_jy(xset,ljj) ;
                             kz2 = DSET_index_to_kz(xset,ljj) ;
                             /* add source, dest, correlation to 1D file */
                             fprintf(fout1D, "%d %d %d %d %d %d %d %d %.6f\n",
                                lii, ljj, ix1, jy1, kz1, ix2, jy2, kz2, car);
                        }
                    }
                    else
                    {
                        /* determine the index in the histogram to add the node */
                        new_node_idx = (int)floor((double)(car-othresh)/(double)binwidth);
                        if ((new_node_idx > nhistnodes) || (new_node_idx < bottom_node_idx))
                        {
                            /* this error should indicate a programming error and should not happen */
                            WARNING_message("Node index %d is out of range [%d,%d)!",new_node_idx,
                            bottom_node_idx, nhistnodes);
                        }
                        else
                        {
                            /* create a node to add to the histogram */
                            new_node = (hist_node*)calloc(1,sizeof(hist_node));
                            if( new_node == NULL )
                            {
                                /* allocate memory for this node, rather than fiddling with 
                                   error handling here, lets just move on */
                                WARNING_message("Could not allocate a new node!");
                            }
                            else
                            {
                 
                                /* populate histogram node */
                                new_node->i = lout; 
                                new_node->j = lin;
                                new_node->corr = car;
                                new_node->next = NULL;

                                /* -- update running memory estimate to reflect memory allocation */ 
                                INC_MEM_STATS( sizeof(hist_node), "hist nodes" );
                                if ((totNumCor % (1024*1024)) == 0) PRINT_MEM_STATS( "hist nodes" );

                                /* populate histogram */
                                new_node->next = histogram[new_node_idx].nodes;
                                histogram[new_node_idx].nodes = new_node;
                                histogram[new_node_idx].nbin++; 

                                /* see if there are enough correlations in the histogram
                                   for the sparsity */
                                if ((totNumCor - histogram[bottom_node_idx].nbin) > nretain)
                                { 
                                    /* delete the list of nodes */
                                    rptr = histogram[bottom_node_idx].nodes;
                                    while(rptr != NULL)
                                    {
                                        tptr = rptr;
                                        rptr = rptr->next;
                                        /* check that the ptr is not null before freeing it*/
                                        if(tptr!= NULL)
                                        {
                                            DEC_MEM_STATS( sizeof(hist_node), "hist nodes" );
                                            free(tptr);
                                        }
                                    }
                                    PRINT_MEM_STATS( "unloaded hist nodes - thresh increase" );

                                    histogram[bottom_node_idx].nodes = NULL;
                                    totNumCor -= histogram[bottom_node_idx].nbin;
                                    histogram[bottom_node_idx].nbin=0;
 
                                    /* get the new threshold */
                                    thresh = (double)histogram[++bottom_node_idx].bin_low;
                                    if(MEM_STAT == 1) INFO_message("Increasing threshold to %3.2f (%d)\n",
                                        thresh,bottom_node_idx); 
                                }

                            } /* else, newptr != NULL */
                        } /* else, new_node_idx in range */
                    } /* else, do_sparsity == 1 */
                 } /* car > thresh */
             } /* this is the end of the critical section */
          } /* end of inner loop over voxels */
       } /* end of outer loop over ref voxels */

       if( ithr == 0 ) fprintf(stderr,".\n") ;

    } /* end OpenMP */
    AFNI_OMP_END ;

    /* update the user so that they know what we are up to */
    INFO_message ("AFNI_OMP finished\n");
    INFO_message ("Found %d (%3.2f%%) correlations above threshold (%f)\n",
       totNumCor, 100.0*((float)totNumCor)/((float)totPosCor), thresh);

   /*----------  Finish up ---------*/

   /*if( dosparsity == 1 )
   {
       for( kout = 0; kout < nhistnodes; kout++ )
       {
           INFO_message("Hist bin %d [%3.3f, %3.3f) [%d, %p]\n",
                kout, histogram[ kout ].bin_low, histogram[ kout ].bin_high,
                histogram[ kout ].nbin, histogram[ kout ].nodes );
       }
   }*/

   /*-- create output dataset --*/
   cset = EDIT_empty_copy( xset ) ;

   /*-- configure the output dataset */
   if( abuc ){
     EDIT_dset_items( cset ,
                        ADN_prefix    , prefix         ,
                        ADN_nvals     , nsubbriks      , /* 2 subbricks, degree and weighted centrality */
                        ADN_ntt       , 0              , /* no time axis */
                        ADN_type      , HEAD_ANAT_TYPE ,
                        ADN_func_type , ANAT_BUCK_TYPE ,
                        ADN_datum_all , MRI_float      ,
                      ADN_none ) ;
   } else {
     EDIT_dset_items( cset ,
                        ADN_prefix    , prefix         ,
                        ADN_nvals     , nsubbriks      , /* 2 subbricks, degree and weighted centrality */
                        ADN_ntt       , nsubbriks      ,  /* num times */
                        ADN_ttdel     , 1.0            ,  /* fake TR */
                        ADN_nsl       , 0              ,  /* no slice offsets */
                        ADN_type      , HEAD_ANAT_TYPE ,
                        ADN_func_type , ANAT_EPI_TYPE  ,
                        ADN_datum_all , MRI_float      ,
                      ADN_none ) ;
   }

   /* add history information to the hearder */
   tross_Make_History( "3dDegreeCentrality" , argc,argv , cset ) ;

   ININFO_message("creating output dataset in memory") ;

   /* -- Configure the subbriks: Binary Degree Centrality */
   subbrik = 0;
   EDIT_BRICK_TO_NOSTAT(cset,subbrik) ;                     /* stat params  */
   /* CC this sets the subbrik scaling factor, which we will probably want
      to do again after we calculate the voxel values */
   EDIT_BRICK_FACTOR(cset,subbrik,1.0) ;                 /* scale factor */

   sprintf(str,"Binary Degree Centrality") ;

   EDIT_BRICK_LABEL(cset,subbrik,str) ;
   EDIT_substitute_brick(cset,subbrik,MRI_float,NULL) ;   /* make array   */


   /* copy measure data into the subbrik */
   bodset = DSET_ARRAY(cset,subbrik);
 
   /* -- Configure the subbriks: Weighted Degree Centrality */
   subbrik = 1;
   EDIT_BRICK_TO_NOSTAT(cset,subbrik) ;                     /* stat params  */
   /* CC this sets the subbrik scaling factor, which we will probably want
      to do again after we calculate the voxel values */
   EDIT_BRICK_FACTOR(cset,subbrik,1.0) ;                 /* scale factor */

   sprintf(str,"Weighted Degree Centrality") ;

   EDIT_BRICK_LABEL(cset,subbrik,str) ;
   EDIT_substitute_brick(cset,subbrik,MRI_float,NULL) ;   /* make array   */

   /* copy measure data into the subbrik */
   wodset = DSET_ARRAY(cset,subbrik);

   /* increment memory stats */
   INC_MEM_STATS( (DSET_NVOX(cset)*DSET_NVALS(cset)*sizeof(float)), "output dset");
   PRINT_MEM_STATS( "outset" );

   /* pull the values out of the histogram */
   if( dosparsity == 0 )
   {
       for( kout = 0; kout < nmask; kout++ )
       {
          if ( imap != NULL )
          {
              ii = imap[kout] ;  /* ii= source voxel (we know that ii is in the mask) */
          }
          else
          {
              ii = kout ;
          }
   
          if( ii >= DSET_NVOX(cset) )
          {
              WARNING_message("Avoiding bodset, wodset overflow %d > %d (%s,%d)\n",
                  ii,DSET_NVOX(cset),__FILE__,__LINE__ );
          }
          else
          {
              bodset[ ii ] = (float)(binaryDC[kout]);
              wodset[ ii ] = (float)(weightedDC[kout]);
          }
       }

       /* we are done with this memory, and can kill it now*/
       if(binaryDC)
       {
           free(binaryDC);
           binaryDC=NULL;
           /* -- update running memory estimate to reflect memory allocation */ 
           DEC_MEM_STATS( nmask*sizeof(long), "binary DC array" );
           PRINT_MEM_STATS( "binaryDC" );
       }
       if(weightedDC)
       {
           free(weightedDC);
           weightedDC=NULL;
           /* -- update running memory estimate to reflect memory allocation */ 
           DEC_MEM_STATS( nmask*sizeof(double), "weighted DC array" );
           PRINT_MEM_STATS( "weightedDC" );
       }
   }
   else
   {

       /* add in the values from the histogram, this is a two stage procedure:
             at first we add in values a whole bin at the time until we get to a point
             where we need to add in a partial bin, then we create a new histogram
             to sort the values in the bin and then add those bins at a time */
       kout = nhistnodes - 1;
       while (( histogram[kout].nbin < nretain ) && ( kout >= 0 ))
       {
           hptr = pptr = histogram[kout].nodes;
           while( hptr != NULL )
           {

               /* determine the indices corresponding to this node */
               if ( imap != NULL )
               {
                   ii = imap[hptr->i] ;  /* ii= source voxel (we know that ii is in the mask) */
               }
               else 
               {
                   ii = hptr->i ;
               }
               if ( imap != NULL )
               {
                   jj = imap[hptr->j] ;  /* ii= source voxel (we know that ii is in the mask) */
               }
               else
               {
                   jj = hptr->j ;
               }

               /* add in the values */
               if(( ii >= DSET_NVOX(cset) ) || ( jj >= DSET_NVOX(cset)))
               {
                   if( ii >= DSET_NVOX(cset))
                   {
                       WARNING_message("Avoiding bodset, wodset overflow (ii) %d > %d\n (%s,%d)\n",
                           ii,DSET_NVOX(cset),__FILE__,__LINE__ );
                   }
                   if( jj >= DSET_NVOX(cset))
                   {
                       WARNING_message("Avoiding bodset, wodset overflow (jj) %d > %d\n (%s,%d)\n",
                           jj,DSET_NVOX(cset),__FILE__,__LINE__ );
                   }
               }
               else
               {
                   bodset[ ii ] += 1.0 ;
                   wodset[ ii ] += (float)(hptr->corr);
                   bodset[ jj ] += 1.0 ;
                   wodset[ jj ] += (float)(hptr->corr);
               }

               if( fout1D != NULL )
               {
                   /* add source, dest, correlation to 1D file */
                   ix1 = DSET_index_to_ix(cset,ii) ;
                   jy1 = DSET_index_to_jy(cset,ii) ;
                   kz1 = DSET_index_to_kz(cset,ii) ;
                   ix2 = DSET_index_to_ix(cset,jj) ;
                   jy2 = DSET_index_to_jy(cset,jj) ;
                   kz2 = DSET_index_to_kz(cset,jj) ;
                   fprintf(fout1D, "%d %d %d %d %d %d %d %d %.6f\n",
                           ii, jj, ix1, jy1, kz1, ix2, jy2, kz2, (float)(hptr->corr));
               }

               /* increment node pointers */
               pptr = hptr;
               hptr = hptr->next;

               /* delete the node */
               if(pptr)
               {
                   /* -- update running memory estimate to reflect memory allocation */ 
                   DEC_MEM_STATS(sizeof( hist_node ), "hist nodes" );
                   /* free the mem */
                   free(pptr);
                   pptr=NULL;
               }
           } 
           /* decrement the number of correlations we wish to retain */
           nretain -= histogram[kout].nbin;
           histogram[kout].nodes = NULL;

           /* go on to the next bin */
           kout--;
       }
       PRINT_MEM_STATS( "hist1 bins free - inc into output" );

        /* if we haven't used all of the correlations that are available, go through and 
           add a subset of the voxels from the remaining bin */
        if(( nretain > 0 ) && (kout >= 0))
        {

            hist_node_head* histogram2 = NULL; 
            hist_node_head* histogram2_save = NULL; 
            int h2nbins = 100;
            float h2binwidth = 0.0;
            int h2ndx=0;

            h2binwidth = (((1.0+binwidth/((float)h2nbins))*histogram[kout].bin_high) - histogram[kout].bin_low) /
               ((float)h2nbins);

            /* allocate the bins */
            if(( histogram2 = (hist_node_head*)malloc(h2nbins*sizeof(hist_node_head))) == NULL )
            {
                if (binaryDC){ free(binaryDC); binaryDC = NULL; }
                if (weightedDC){ free(weightedDC); weightedDC = NULL; }
                if (histogram){ histogram = free_histogram(histogram, nhistnodes); }
                ERROR_message( "Could not allocate %d byte array for histogram2\n",
                    h2nbins*sizeof(hist_node_head)); 
            }
            else {
                /* -- update running memory estimate to reflect memory allocation */ 
                histogram2_save = histogram2;
                INC_MEM_STATS(( h2nbins*sizeof(hist_node_head )), "hist bins");
                PRINT_MEM_STATS( "hist2" );
            }
   
            /* initiatize the bins */ 
            for( kin = 0; kin < h2nbins; kin++ )
            {
                histogram2[ kin ].bin_low = histogram[kout].bin_low + kin*h2binwidth;
                histogram2[ kin ].bin_high = histogram2[ kin ].bin_low + h2binwidth;
                histogram2[ kin ].nbin = 0;
                histogram2[ kin ].nodes = NULL; 
                /*INFO_message("Hist2 bin %d [%3.3f, %3.3f) [%d, %p]\n",
                    kin, histogram2[ kin ].bin_low, histogram2[ kin ].bin_high,
                    histogram2[ kin ].nbin, histogram2[ kin ].nodes );*/
            }

            /* move correlations from histogram to histgram2 */
            INFO_message ("Adding %d nodes from histogram to histogram2",histogram[kout].nbin);
            while ( histogram[kout].nodes != NULL )
            {
                hptr = histogram[kout].nodes;
                h2ndx = (int)floor((double)(hptr->corr - histogram[kout].bin_low)/(double)h2binwidth);
                if(( h2ndx < h2nbins ) && ( h2ndx >= 0 ))
                {
                    histogram[kout].nodes = hptr->next;
                    hptr->next = histogram2[h2ndx].nodes;
                    histogram2[h2ndx].nodes = hptr; 
                    histogram2[h2ndx].nbin++;
                    histogram[kout].nbin--;
                }
                else
                {
                    WARNING_message("h2ndx %d is not in range [0,%d) :: %.10f,%.10f\n",h2ndx,h2nbins,hptr->corr, histogram[kout].bin_low);
                }
               
            }

            /* free the remainder of histogram */
            {
                int nbins_rem = 0;
                for(ii = 0; ii < nhistnodes; ii++) nbins_rem+=histogram[ii].nbin;
                histogram = free_histogram(histogram, nhistnodes);
                PRINT_MEM_STATS( "free remainder of histogram1" );
            }

            kin = h2nbins - 1;
            while (( nretain > 0 ) && ( kin >= 0 ))
            {
                hptr = pptr = histogram2[kin].nodes;
                while( hptr != NULL )
                {
     
                    /* determine the indices corresponding to this node */
                    if ( imap != NULL )
                    {
                        ii = imap[hptr->i] ;  
                    }
                    else
                    {
                        ii = hptr->i ;
                    }
                    if ( imap != NULL )
                    {
                        jj = imap[hptr->j] ; 
                    }
                    else
                    {
                        jj = hptr->j ;
                    }

                    /* add in the values */
                    if(( ii >= DSET_NVOX(cset) ) || ( jj >= DSET_NVOX(cset)))
                    {
                        if( ii >= DSET_NVOX(cset))
                        {
                            WARNING_message("Avoiding bodset, wodset overflow (ii) %d > %d\n (%s,%d)\n",
                                ii,DSET_NVOX(cset),__FILE__,__LINE__ );
                        }
                        if( jj >= DSET_NVOX(cset))
                        {
                            WARNING_message("Avoiding bodset, wodset overflow (jj) %d > %d\n (%s,%d)\n",
                                jj,DSET_NVOX(cset),__FILE__,__LINE__ );
                        }
                    }
                    else
                    {
                        bodset[ ii ] += 1.0 ;
                        wodset[ ii ] += (float)(hptr->corr);
                        bodset[ jj ] += 1.0 ;
                        wodset[ jj ] += (float)(hptr->corr);
                    }
                    if( fout1D != NULL )
                    {
                        /* add source, dest, correlation to 1D file */
                        ix1 = DSET_index_to_ix(cset,ii) ;
                        jy1 = DSET_index_to_jy(cset,ii) ;
                        kz1 = DSET_index_to_kz(cset,ii) ;
                        ix2 = DSET_index_to_ix(cset,jj) ;
                        jy2 = DSET_index_to_jy(cset,jj) ;
                        kz2 = DSET_index_to_kz(cset,jj) ;
                        fprintf(fout1D, "%d %d %d %d %d %d %d %d %.6f\n",
                            ii, jj, ix1, jy1, kz1, ix2, jy2, kz2, (float)(hptr->corr));
                    }

                    /* increment node pointers */
                    pptr = hptr;
                    hptr = hptr->next;

                    /* delete the node */
                    if(pptr)
                    {
                        free(pptr);
                        DEC_MEM_STATS(( sizeof(hist_node) ), "hist nodes");
                        pptr=NULL;
                    }
                }
 
                /* decrement the number of correlations we wish to retain */
                nretain -= histogram2[kin].nbin;
                histogram2[kin].nodes = NULL;

                /* go on to the next bin */
                kin--;
            }
            PRINT_MEM_STATS("hist2 nodes free - incorporated into output");

            /* we are finished with histogram2 */
            {
                histogram2 = free_histogram(histogram2, h2nbins);
                /* -- update running memory estimate to reflect memory allocation */ 
                PRINT_MEM_STATS( "free hist2" );
            }

            if (nretain < 0 )
            {
                WARNING_message( "Went over sparsity goal %d by %d, with a resolution of %f",
                      ngoal, -1*nretain, h2binwidth);
            }
        }
        if (nretain > 0 )
        {
            WARNING_message( "Was not able to meet goal of %d (%3.2f%%) correlations, %d (%3.2f%%) correlations passed the threshold of %3.2f, maybe you need to change the threshold or the desired sparsity?",
                  ngoal, 100.0*((float)ngoal)/((float)totPosCor), totNumCor, 100.0*((float)totNumCor)/((float)totPosCor),  thresh);
        }
   }

   INFO_message("Done..\n") ;

   /* update running memory statistics to reflect freeing the vectim */
   DEC_MEM_STATS(((xvectim->nvec*sizeof(int)) +
                       ((xvectim->nvec)*(xvectim->nvals))*sizeof(float) +
                       sizeof(MRI_vectim)), "vectim");

   /* toss some trash */
   VECTIM_destroy(xvectim) ;
   DSET_delete(xset) ;
   if(fout1D!=NULL)fclose(fout1D);

   PRINT_MEM_STATS( "vectim unload" );

   if (weightedDC) free(weightedDC) ; weightedDC = NULL;
   if (binaryDC) free(binaryDC) ; binaryDC = NULL;
   
   /* finito */
   INFO_message("Writing output dataset to disk [%s bytes]",
                commaized_integer_string(cset->dblk->total_bytes)) ;

   /* write the dataset */
   DSET_write(cset) ;
   WROTE_DSET(cset) ;

   /* increment our memory stats, since we are relying on the header for this
      information, we update the stats before actually freeing the memory */
   DEC_MEM_STATS( (DSET_NVOX(cset)*DSET_NVALS(cset)*sizeof(float)), "output dset");

   /* free up the output dataset memory */
   DSET_unload(cset) ;
   DSET_delete(cset) ;

   /* force a print */
   MEM_STAT = 1;
   PRINT_MEM_STATS( "Fin" );

   exit(0) ;
}
Exemple #29
0
int main( int argc , char * argv[] )
{
   int iarg=1 , dcode=0 , maxgap=2 , nftot=0 ;
   char * prefix="zfillin" , * dstr=NULL;
   THD_3dim_dataset * inset , * outset ;
   MRI_IMAGE * brim ;
   int verb=0 ;

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
      printf("Usage: 3dZFillin [options] dataset\n"
             "Extracts 1D rows in the given direction from a 3D dataset,\n"
             "searches for zeros that are 'close' to nonzero values in the row,\n"
             "and replaces the zeros with the closest nonzero neighbor.\n"
             "\n"
             "OPTIONS:\n"
             " -maxstep N  = set the maximum distance to a neighbor\n"
             "                [default=2].\n"
             " -dir D     = set the direction of fill to 'D', which can\n"
             "                be one of the following:\n"
             "                  A-P, P-A, I-S, S-I, L-R, R-L, x, y, z\n"
             "                The first 6 are anatomical directions;\n"
             "                the last 3 are reference to the dataset\n"
             "                internal axes [no default value].\n"
             " -prefix P  = set the prefix to 'P' for the output dataset.\n"
             "\n"
             "N.B.: * If the input dataset has more than one sub-brick,\n"
             "        only the first one will be processed.\n"
             "      * At this time, 3dZFillin only works on byte-valued datasets\n"
             "\n"
             "This program's only purpose is to fill up the Talairach Daemon\n"
             "bricks obtained from the UT San Antonio database.\n"
             "\n"
            ) ;
      PRINT_COMPILE_DATE ; exit(0) ;
   }

   mainENTRY("3dZFillin main") ; machdep() ; AFNI_logger("3dZfillin",argc,argv) ;
   PRINT_VERSION(3dZFillin") ;

   /*-- scan args --*/

   while( iarg < argc && argv[iarg][0] == '-' ){

      if( strncmp(argv[iarg],"-verb",5) == 0 ){
         verb++ ; iarg++ ; continue ;
      }

      if( strcmp(argv[iarg],"-prefix") == 0 ){
         prefix = argv[++iarg] ;
         if( !THD_filename_ok(prefix) ){
            fprintf(stderr,"*** Illegal string after -prefix!\n"); exit(1) ;
         }
         iarg++ ; continue ;
      }

      if( strcmp(argv[iarg],"-maxstep") == 0 ){
         maxgap = strtol( argv[++iarg] , NULL , 10 ) ;
         if( maxgap < 1 ){
            fprintf(stderr,"*** Illegal value after -maxgap!\n"); exit(1);
         }
         iarg++ ; continue ;
      }

      if( strcmp(argv[iarg],"-dir") == 0 ){
         dstr = argv[++iarg] ;
         iarg++ ; continue ;
      }

      fprintf(stderr,"*** Illegal option: %s\n",argv[iarg]) ; exit(1) ;
   }

   if( dstr == NULL ){
      fprintf(stderr,"*** No -dir option on command line!\n"); exit(1);
   }
   if( iarg >= argc ){
      fprintf(stderr,"*** No input dataset on command line!\n"); exit(1);
   }

   inset = THD_open_dataset( argv[iarg] ) ;
   if( inset == NULL ){
      fprintf(stderr,"*** Can't open dataset %s\n",argv[iarg]); exit(1);
   }

   outset = EDIT_empty_copy( inset ) ;
   EDIT_dset_items( outset , ADN_prefix , prefix , ADN_none ) ;
   if( THD_deathcon() && THD_is_file( DSET_HEADNAME(outset) ) ){
      fprintf(stderr,"** Output file %s exists -- cannot overwrite!\n",
              DSET_HEADNAME(outset) ) ;
      exit(1) ;
   }

   tross_Copy_History( inset , outset ) ;
   tross_Make_History( "3dZFillin" , argc,argv , outset ) ;

   if( DSET_NVALS(inset) > 1 ){
      fprintf(stderr,"++ WARNING: input dataset has more than one sub-brick!\n");
      EDIT_dset_items( outset ,
                         ADN_ntt   , 0 ,
                         ADN_nvals , 1 ,
                       ADN_none ) ;
   }

   if( DSET_BRICK_TYPE(outset,0) != MRI_byte ){
      fprintf(stderr,"*** This program only works on byte datasets!\n");
      exit(1) ;
   }

   switch( *dstr ){
      case 'x': dcode = 1 ; break ;
      case 'y': dcode = 2 ; break ;
      case 'z': dcode = 3 ; break ;

      default:
        if( *dstr == ORIENT_tinystr[outset->daxes->xxorient][0] ||
            *dstr == ORIENT_tinystr[outset->daxes->xxorient][1]   ) dcode = 1 ;

        if( *dstr == ORIENT_tinystr[outset->daxes->yyorient][0] ||
            *dstr == ORIENT_tinystr[outset->daxes->yyorient][1]   ) dcode = 2 ;

        if( *dstr == ORIENT_tinystr[outset->daxes->zzorient][0] ||
            *dstr == ORIENT_tinystr[outset->daxes->zzorient][1]   ) dcode = 3 ;
      break ;
   }
   if( dcode == 0 ){
      fprintf(stderr,"*** Illegal -dir direction!\n") ; exit(1) ;
   }
   if( verb )
      fprintf(stderr,"++ Direction = axis %d in dataset\n",dcode) ;

   DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ;
   brim = mri_copy( DSET_BRICK(inset,0) ) ;
   DSET_unload(inset) ;
   EDIT_substitute_brick( outset , 0 , brim->kind , mri_data_pointer(brim) ) ;
   nftot = THD_dataset_zfillin( outset , 0 , dcode , maxgap ) ;
   fprintf(stderr,"++ Number of voxels filled = %d\n",nftot) ;
   if (DSET_write(outset) != False) {
      fprintf(stderr,"++ output dataset: %s\n",DSET_BRIKNAME(outset)) ;
      exit(0) ;
   } else {
      fprintf(stderr,
         "** 3dZFillin: Failed to write output!\n" ) ;
      exit(1) ;
   }
   
}
Exemple #30
0
int main(int argc, char *argv[]) {
	int i,j,k,m,n,aa,ii,jj,kk,mm,rr;
	int iarg;
	int nmask1=0;
	int nmask2=0;
	THD_3dim_dataset *insetFA = NULL, *insetV1 = NULL, 
		*insetMD = NULL, *insetL1 = NULL;
	THD_3dim_dataset *insetEXTRA=NULL; 
	THD_3dim_dataset *mset2=NULL; 
	THD_3dim_dataset *mset1=NULL; 
	THD_3dim_dataset *outsetMAP=NULL, *outsetMASK=NULL;
	char *prefix="tracky";
	int LOG_TYPE=0;
	char in_FA[300];
	char in_V1[300];
	char in_MD[300];
	char in_L1[300];
	int EXTRAFILE=0; // switch for whether other file is input as WM map

	char OUT_bin[300];
	char OUT_tracstat[300];
	char prefix_mask[300];
	char prefix_map[300];

	// FACT algopts
	FILE *fout0;
	float MinFA=0.2,MaxAngDeg=45,MinL=20.0;
	float MaxAng;
	int SeedPerV[3]={2,2,2};
	int ArrMax=0;
	float tempvmagn;
  
	int Nvox=-1;   // tot number vox
	int Dim[3]={0,0,0}; // dim in each dir
	int Nseed=0,M=30,bval=1000;
	int DimSeed[3]; // number of seeds there will be
	float Ledge[3]; // voxel edge lengths

	int *ROI1, *ROI2;
	short int *temp_arr;
	char *temp_byte; 
	int **Tforw, **Tback;
	int **Ttot;
	float **flTforw, **flTback;
	float ****coorded;
	int ****INDEX;
	int len_forw, len_back; // int count of num of squares through
	float phys_forw[1], phys_back[1];
	int idx;

	float ave_tract_len, ave_tract_len_phys;
	int inroi1, inroi2, KEEPIT; // switches for detecting
	int in[3]; // to pass to trackit
	float physin[3]; // also for trackit, physical loc, 
	int totlen; 
	float totlen_phys;
	int Numtract;

	int READS_in;
	float READS_fl;
	int end[2][3];
	int test_ind[2][3];

	int  roi3_ct=0, id=0;
	float roi3_mu_MD = 0.,roi3_mu_RD = 0.,roi3_mu_L1 = 0.,roi3_mu_FA = 0.;  
	float roi3_sd_MD = 0.,roi3_sd_RD = 0.,roi3_sd_L1 = 0.,roi3_sd_FA = 0.;  
	float tempMD,tempFA,tempRD,tempL1;
	char dset_or[4] = "RAI";
	THD_3dim_dataset *dsetn;
	int TV_switch[3] = {0,0,0};
	TAYLOR_BUNDLE *tb=NULL;
	TAYLOR_TRACT *tt=NULL;
	char *mode = "NI_fast_binary";
	NI_element *nel=NULL;
	int dump_opts=0;

	tv_io_header header1 = {.id_string = "TRACK\0", 
				.origin = {0,0,0},   
				.n_scalars = 3,
				.scal_n[0] = "FA",
				.scal_n[1] = "MD",
				.scal_n[2] = "L1",
				.n_properties = 0,
				.vox_to_ras = {{0.,0.,0.,0.},{0.,0.,0.,0.},
					       {0.,0.,0.,0.},{0.,0.,0.,0.}},
				// reset this later based on actual data set
				.voxel_order = "RAI\0", 
				.invert_x = 0,
				.invert_y = 0,
				.invert_z = 0,
				.swap_xy = 0,
				.swap_yz = 0,
				.swap_zx = 0,
				.n_count = 0,
				.version = 2,
				.hdr_size = 1000};
	
  	// for testing names...
	char *postfix[4]={"+orig.HEAD\0",".nii.gz\0",".nii\0","+tlrc.HEAD\0"};
  	int FOUND =-1;
	int RECORD_ORIG = 0; 
	float Orig[3] = {0.0,0.0,0.0};

	mainENTRY("3dTrackID"); machdep(); 
  
	// ****************************************************************
	// ****************************************************************
	//                    load AFNI stuff
	// ****************************************************************
	// ****************************************************************

	INFO_message("version: MU");

	/** scan args **/
	if (argc == 1) { usage_TrackID(1); exit(0); }
	iarg = 1;
	while( iarg < argc && argv[iarg][0] == '-' ){
		if( strcmp(argv[iarg],"-help") == 0 || 
			 strcmp(argv[iarg],"-h") == 0 ) {
			usage_TrackID(strlen(argv[iarg])>3 ? 2:1);
			exit(0);
		}
    
		if( strcmp(argv[iarg],"-verb") == 0) {
			if( ++iarg >= argc ) 
				ERROR_exit("Need argument after '-verb'") ;
			set_tract_verb(atoi(argv[iarg]));
			iarg++ ; continue ;
		}

		if( strcmp(argv[iarg],"-write_opts") == 0) {
			dump_opts=1;
			iarg++ ; continue ;
		}
    
		if( strcmp(argv[iarg],"-rec_orig") == 0) {
			RECORD_ORIG=1;
			iarg++ ; continue ;
		}
    
		if( strcmp(argv[iarg],"-tract_out_mode") == 0) {
			if( ++iarg >= argc ) 
				ERROR_exit("Need argument after '-tract_out_mode'") ;
			if (strcmp(argv[iarg], "NI_fast_binary") &&
				 strcmp(argv[iarg], "NI_fast_text") &&
				 strcmp(argv[iarg], "NI_slow_binary") &&
				 strcmp(argv[iarg], "NI_slow_text") ) {
				ERROR_message("Bad value (%s) for -tract_out_mode",argv[iarg]);
				exit(1);
			}  
			mode = argv[iarg];
			iarg++ ; continue ;
		}
    
		if( strcmp(argv[iarg],"-mask1") == 0 ){
			if( ++iarg >= argc ) 
				ERROR_exit("Need argument after '-mask1'") ;
			mset1 = THD_open_dataset( argv[iarg] ) ;
			if( mset1 == NULL ) 
				ERROR_exit("Can't open mask1 dataset '%s'", argv[iarg]) ;
			DSET_load(mset1) ; CHECK_LOAD_ERROR(mset1) ;
			nmask1 = DSET_NVOX(mset1) ;

			iarg++ ; continue ;
		}
		if( strcmp(argv[iarg],"-mask2") == 0 ){
			if( ++iarg >= argc ) 
				ERROR_exit("Need argument after '-mask2'") ;
			mset2 = THD_open_dataset( argv[iarg] ) ;
			if( mset2 == NULL ) 
				ERROR_exit("Can't open mask2 dataset '%s'",
							  argv[iarg]) ;
			DSET_load(mset2) ; CHECK_LOAD_ERROR(mset2) ;
			nmask2 = DSET_NVOX(mset2) ;
		
			iarg++ ; continue ;
		}
	 
		if( strcmp(argv[iarg],"-prefix") == 0 ){
			iarg++ ; if( iarg >= argc ) 
							ERROR_exit("Need argument after '-prefix'");
			prefix = strdup(argv[iarg]) ;
			if( !THD_filename_ok(prefix) ) 
				ERROR_exit("Illegal name after '-prefix'");
			iarg++ ; continue ;
		}
	 
		if( strcmp(argv[iarg],"-input") == 0 ){
			iarg++ ; if( iarg >= argc ) 
							ERROR_exit("Need argument after '-input'");

			for( i=0 ; i<4 ; i++) {
				sprintf(in_FA,"%s_FA%s", argv[iarg],postfix[i]); 
				if(THD_is_ondisk(in_FA)) {
					FOUND = i;
					break;
				}
			}
			insetFA = THD_open_dataset(in_FA) ;
			if( (insetFA == NULL ) || (FOUND==-1))
				ERROR_exit("Can't open dataset '%s': for FA.",in_FA);
			
			DSET_load(insetFA) ; CHECK_LOAD_ERROR(insetFA) ;
			Nvox = DSET_NVOX(insetFA) ;
			Dim[0] = DSET_NX(insetFA); Dim[1] = DSET_NY(insetFA); 
			Dim[2] = DSET_NZ(insetFA); 
			Ledge[0] = fabs(DSET_DX(insetFA)); Ledge[1] = fabs(DSET_DY(insetFA)); 
			Ledge[2] = fabs(DSET_DZ(insetFA)); 
			Orig[0] = DSET_XORG(insetFA); Orig[1] = DSET_YORG(insetFA);
			Orig[2] = DSET_ZORG(insetFA);

			// check tot num vox match (as proxy for dims...)
			if( (Nvox != nmask1) || (Nvox != nmask2) )
				ERROR_exit("Input dataset does not match both mask volumes!");
		
      
			// this stores the original data file orientation for later use,
			// as well since we convert everything to RAI temporarily, as
			// described below
			header1.voxel_order[0]=ORIENT_typestr[insetFA->daxes->xxorient][0];
			header1.voxel_order[1]=ORIENT_typestr[insetFA->daxes->yyorient][0];
			header1.voxel_order[2]=ORIENT_typestr[insetFA->daxes->zzorient][0];
			for( i=0 ; i<3 ; i++) {
				header1.dim[i] = Dim[i];
				header1.voxel_size[i] = Ledge[i];
				// will want this when outputting file later for TrackVis.
				TV_switch[i] = !(dset_or[i]==header1.voxel_order[i]);
			}
			dset_or[3]='\0';
      
			FOUND = -1;
			for( i=0 ; i<4 ; i++) {
				sprintf(in_V1,"%s_V1%s", argv[iarg],postfix[i]); 
				if(THD_is_ondisk(in_V1)) {
					FOUND = i;
					break;
				}
			}
			insetV1 = THD_open_dataset(in_V1);
			if( insetV1 == NULL ) 
				ERROR_exit("Can't open dataset '%s':V1",in_V1);
			DSET_load(insetV1) ; CHECK_LOAD_ERROR(insetV1) ;
		
			FOUND = -1;
			for( i=0 ; i<4 ; i++) {
				sprintf(in_L1,"%s_L1%s", argv[iarg],postfix[i]); 
				if(THD_is_ondisk(in_L1)) {
					FOUND = i;
					break;
				}
			}
			insetL1 = THD_open_dataset(in_L1);
			if( insetL1 == NULL ) 
				ERROR_exit("Can't open dataset '%s':L1",in_L1);
			DSET_load(insetL1) ; CHECK_LOAD_ERROR(insetL1) ;

			FOUND = -1;
			for( i=0 ; i<4 ; i++) {
				sprintf(in_MD,"%s_MD%s", argv[iarg],postfix[i]); 
				if(THD_is_ondisk(in_MD)) {
					FOUND = i;
					break;
				}
			}
			insetMD = THD_open_dataset(in_MD);
			if( insetMD == NULL ) 
				ERROR_exit("Can't open dataset '%s':MD",in_MD);
			DSET_load(insetMD) ; CHECK_LOAD_ERROR(insetMD) ;

			iarg++ ; continue ;
		}

		if( strcmp(argv[iarg],"-algopt") == 0 ){
			iarg++ ; 
			if( iarg >= argc ) 
				ERROR_exit("Need argument after '-algopt'");
		
			if (!(nel = ReadTractAlgOpts(argv[iarg]))) {
				ERROR_message("Failed to read options in %s\n", argv[iarg]);
				exit(19);
			}
			if (NI_getTractAlgOpts(nel, &MinFA, &MaxAngDeg, &MinL, 
										  SeedPerV, &M, &bval)) {
				ERROR_message("Failed to get options");
				exit(1);
			}
			NI_free_element(nel); nel=NULL;
      
			iarg++ ; continue ;
		}

		if( strcmp(argv[iarg],"-logic") == 0 ){
			iarg++ ; if( iarg >= argc ) 
							ERROR_exit("Need argument after '-logic'");

			INFO_message("ROI logic type is: %s",argv[iarg]);
			if( strcmp(argv[iarg],"AND") == 0 ) 
				LOG_TYPE = 1;
			else if( strcmp(argv[iarg],"OR") == 0 ) 
				LOG_TYPE = 0;
			else if( strcmp(argv[iarg],"ALL") == 0 )
				LOG_TYPE = -1;
			else 
				ERROR_exit("Illegal after '-logic': need 'OR' or 'AND'");
			iarg++ ; continue ;
		}
    
		//@@
		if( strcmp(argv[iarg],"-extra_set") == 0) {
			if( ++iarg >= argc ) 
				ERROR_exit("Need argument after '-extra_set'");
			EXTRAFILE = 1; // switch on

			insetEXTRA = THD_open_dataset(argv[iarg]);
			if( (insetEXTRA == NULL ) )
				ERROR_exit("Can't open dataset '%s': for extra set.",argv[iarg]);
			DSET_load(insetEXTRA) ; CHECK_LOAD_ERROR(insetEXTRA) ;

			if( !((Dim[0] == DSET_NX(insetEXTRA)) && (Dim[1] == DSET_NY(insetEXTRA)) && (Dim[2] == DSET_NZ(insetEXTRA))))
				ERROR_exit("Dimensions of extra set '%s' don't match those of the DTI prop ones ('%s', etc.).",argv[iarg], in_FA);
			
			iarg++ ; continue ;
		}


		ERROR_message("Bad option '%s'\n",argv[iarg]) ;
		suggest_best_prog_option(argv[0], argv[iarg]);
		exit(1);
	}
	 
	if (iarg < 4) {
		ERROR_message("Too few options. Try -help for details.\n");
		exit(1);
	}
	 
	if (dump_opts) {
      nel = NI_setTractAlgOpts(NULL, &MinFA, &MaxAngDeg, &MinL, 
										 SeedPerV, &M, &bval);
      WriteTractAlgOpts(prefix, nel);
      NI_free_element(nel); nel=NULL;
	}
	 
        
	// Process the options a little 
	for( i=0 ; i<3 ; i++)
		DimSeed[i] = Dim[i]*SeedPerV[i];
	Nseed = Nvox*SeedPerV[0]*SeedPerV[1]*SeedPerV[2];
	 
	// convert to cos of rad value for comparisons, instead of using acos()
	MaxAng = cos(CONV*MaxAngDeg); 
	 
	// switch to add header-- option for now, added Sept. 2012
	// for use with map_TrackID to map tracks to different space
	if(RECORD_ORIG) {
		for( i=0 ; i<3 ; i++)
			header1.origin[i] = Orig[i];
	}
	 
	// at some point, we will have to convert indices into
	// pseudo-locations; being forced into this choice means that
	// different data set orientations would be represented differently
	// and incorrectly in some instances... so, for now, we'll resample
	// everything to RAI, and then resample back later.  guess this will
	// just slow things down slightly.
	 
	// have all be RAI for processing here
	if(TV_switch[0] || TV_switch[1] || TV_switch[2]) {
		dsetn = r_new_resam_dset(insetFA, NULL, 0.0, 0.0, 0.0,
										 dset_or, RESAM_NN_TYPE, NULL, 1, 0);
		DSET_delete(insetFA); 
		insetFA=dsetn;
		dsetn=NULL;
		
		dsetn = r_new_resam_dset(insetMD, NULL, 0.0, 0.0, 0.0,
										 dset_or, RESAM_NN_TYPE, NULL, 1, 0);
		DSET_delete(insetMD); 
		insetMD=dsetn;
		dsetn=NULL;
		
		dsetn = r_new_resam_dset(insetV1, NULL, 0.0, 0.0, 0.0,
										 dset_or, RESAM_NN_TYPE, NULL, 1, 0);
		DSET_delete(insetV1); 
		insetV1=dsetn;
		dsetn=NULL;
		
		dsetn = r_new_resam_dset(insetL1, NULL, 0.0, 0.0, 0.0,
										 dset_or, RESAM_NN_TYPE, NULL, 1, 0);
		DSET_delete(insetL1); 
		insetL1=dsetn;
		dsetn=NULL;
		
		dsetn = r_new_resam_dset(mset1, NULL, 0.0, 0.0, 0.0,
										 dset_or, RESAM_NN_TYPE, NULL, 1, 0);
		DSET_delete(mset1); 
		mset1=dsetn;
		dsetn=NULL;
		
		dsetn = r_new_resam_dset(mset2, NULL, 0.0, 0.0, 0.0,
										 dset_or, RESAM_NN_TYPE, NULL, 1, 0);
		DSET_delete(mset2); 
		mset2=dsetn;
		dsetn=NULL;

		if(EXTRAFILE) {
			dsetn = r_new_resam_dset(insetEXTRA, NULL, 0.0, 0.0, 0.0,
											 dset_or, RESAM_NN_TYPE, NULL, 1, 0);
			DSET_delete(insetEXTRA); 
			insetEXTRA=dsetn;
			dsetn=NULL;
		}


	}
	 
	 

	// ****************************************************************
	// ****************************************************************
	//                    make arrays for tracking
	// ****************************************************************
	// ****************************************************************

	// for temp storage array, just a multiple of longest dimension!
	if(Dim[0] > Dim[1])
		ArrMax = Dim[0] * 4;
	else
		ArrMax = Dim[1] * 4;
	if(4*Dim[2] > ArrMax)
		ArrMax = Dim[2] * 4;

	ROI1 = (int *)calloc(Nvox, sizeof(int)); 
	ROI2 = (int *)calloc(Nvox, sizeof(int)); 
	temp_arr = (short int *)calloc(Nvox, sizeof(short int)); 
	temp_byte = (char *)calloc(Nvox, sizeof(char)); 
	// temp storage whilst tracking
	Tforw = calloc(ArrMax, sizeof(Tforw)); 
	for(i=0 ; i<ArrMax ; i++) 
		Tforw[i] = calloc(3, sizeof(int)); 
	Ttot = calloc(2*ArrMax , sizeof(Ttot)); 
	for(i=0 ; i<2*ArrMax ; i++) 
		Ttot[i] = calloc(3, sizeof(int)); 
	Tback = calloc(ArrMax, sizeof(Tback)); 
	for(i=0 ; i<ArrMax ; i++) 
		Tback[i] = calloc(3, sizeof(int)); 
	// temp storage whilst tracking, physical loc
	flTforw = calloc(ArrMax, sizeof(flTforw)); 
	for(i=0 ; i<ArrMax ; i++) 
		flTforw[i] = calloc(3, sizeof(int)); 
	flTback = calloc(ArrMax,sizeof(flTback)); 
	for(i=0 ; i<ArrMax ; i++) 
		flTback[i] = calloc(3, sizeof(int)); 
	if( (ROI1 == NULL) || (ROI2 == NULL) || (temp_arr == NULL) 
		 || (Tforw == NULL) || (Tback == NULL) || (flTforw == NULL) 
		 || (flTback == NULL) || (Ttot == NULL)) {
		fprintf(stderr, "\n\n MemAlloc failure.\n\n");
		exit(12);
	}
  
	coorded = (float ****) calloc( Dim[0], sizeof(float ***) );
	for ( i = 0 ; i < Dim[0] ; i++ ) 
		coorded[i] = (float ***) calloc( Dim[1], sizeof(float **) );
	for ( i = 0 ; i < Dim[0] ; i++ ) 
		for ( j = 0 ; j < Dim[1] ; j++ ) 
			coorded[i][j] = (float **) calloc( Dim[2], sizeof(float *) );
	for ( i=0 ; i<Dim[0] ; i++ ) 
		for ( j=0 ; j<Dim[1] ; j++ ) 
			for ( k= 0 ; k<Dim[2] ; k++ ) //3 comp of V1 and FA
				coorded[i][j][k] = (float *) calloc( 4, sizeof(float) ); 
  
	INDEX = (int ****) calloc( Dim[0], sizeof(int ***) );
	for ( i = 0 ; i < Dim[0] ; i++ ) 
		INDEX[i] = (int ***) calloc( Dim[1], sizeof(int **) );
	for ( i = 0 ; i < Dim[0] ; i++ ) 
		for ( j = 0 ; j < Dim[1] ; j++ ) 
			INDEX[i][j] = (int **) calloc( Dim[2], sizeof(int *) );
	for ( i=0 ; i<Dim[0] ; i++ ) 
		for ( j=0 ; j<Dim[1] ; j++ ) 
			for ( k= 0 ; k<Dim[2] ; k++ ) 
				INDEX[i][j][k] = (int *) calloc( 4,  sizeof(int) );

	// this statement will never be executed if allocation fails above
	if( (INDEX == NULL) || (coorded == NULL) ) { 
		fprintf(stderr, "\n\n MemAlloc failure.\n\n");
		exit(122);
	}
  
	for(i=0 ; i<Nvox ; i++) {
		if(THD_get_voxel( mset1, i, 0) >0.5){
			ROI1[i] = 1;
		}
		if(THD_get_voxel( mset2, i, 0) >0.5)
			ROI2[i] = 1;
	}

	// set up eigvecs in 3D coord sys,
	// mark off where ROIs are and keep index handy
	idx=0;
	for( k=0 ; k<Dim[2] ; k++ ) 
		for( j=0 ; j<Dim[1] ; j++ ) 
			for( i=0 ; i<Dim[0] ; i++ ) {
				for( m=0 ; m<3 ; m++ ) 
					coorded[i][j][k][m] = THD_get_voxel(insetV1, idx, m);
				if(EXTRAFILE)
					coorded[i][j][k][3] = THD_get_voxel(insetEXTRA, idx, 0); 
				else
					coorded[i][j][k][3] = THD_get_voxel(insetFA, idx, 0); 
   
				// make sure that |V1| == 1 for all eigenvects, otherwise it's
				/// a problem in the tractography; currently, some from
				// 3dDWItoDT do not have this property...
				tempvmagn = sqrt(coorded[i][j][k][0]*coorded[i][j][k][0]+
									  coorded[i][j][k][1]*coorded[i][j][k][1]+
									  coorded[i][j][k][2]*coorded[i][j][k][2]);
				if( tempvmagn<0.99 ) 
					for( m=0 ; m<3 ; m++ ) 
						coorded[i][j][k][m]/= tempvmagn;
   
				INDEX[i][j][k][0] =idx; // first value is the index itself
				if( ROI1[idx]==1 ) 
					INDEX[i][j][k][1]=1; // second value identifies ROI1 mask
				else
					INDEX[i][j][k][1]=0;
				if( ROI2[idx]==1 )
					INDEX[i][j][k][2]=1; // third value identifies ROI2 mask
				else
					INDEX[i][j][k][2]=0;

				// fourth value will be counter for number of kept tracks
				// passing through
				INDEX[i][j][k][3] = 0;  
				idx+= 1;
			}
  
	// *************************************************************
	// *************************************************************
	//                    Beginning of main loop
	// *************************************************************
	// *************************************************************

	Numtract = 0;
	ave_tract_len = 0.;
	ave_tract_len_phys = 0.;
 
	sprintf(OUT_bin,"%s.trk",prefix);
	if( (fout0 = fopen(OUT_bin, "w")) == NULL) {
		fprintf(stderr, "Error opening file %s.",OUT_bin);
		exit(16);
	}
	fwrite(&header1,sizeof(tv_io_header),1,fout0);
  
	if (get_tract_verb()) {
		INFO_message("Begin tracking...");
	}

	tb = AppCreateBundle(NULL, 0, NULL, insetFA); // start bundle
	id = 0;
	for( k=0 ; k<Dim[2] ; k++ ) 
		for( j=0 ; j<Dim[1] ; j++ ) 
			for( i=0 ; i<Dim[0] ; i++ ) 
				if(coorded[i][j][k][3] >= MinFA) { 
					for( ii=0 ; ii<SeedPerV[0] ; ii++ ) 
						for( jj=0 ; jj<SeedPerV[1] ; jj++ ) 
							for( kk=0 ; kk<SeedPerV[2] ; kk++ ) {

								in[0] = i;
								in[1] = j;
								in[2] = k;
								physin[0] = ((float) in[0] + 
												 (0.5 + (float) ii)/SeedPerV[0])*Ledge[0];
								physin[1] = ((float) in[1] + 
												 (0.5 + (float) jj)/SeedPerV[1])*Ledge[1];
								physin[2] = ((float) in[2] + 
												 (0.5 + (float) kk)/SeedPerV[2])*Ledge[2];
      
								len_forw = TrackIt(coorded, in, physin, Ledge, Dim, 
														 MinFA, MaxAng, ArrMax, Tforw, 
														 flTforw, 1, phys_forw);
      
								// reset, because it's changed in TrackIt func
								in[0] = i; 
								in[1] = j;
								in[2] = k;

								physin[0] = ((float) in[0] + 
												 (0.5 + (float) ii)/SeedPerV[0])*Ledge[0];
								physin[1] = ((float) in[1] + 
												 (0.5 + (float) jj)/SeedPerV[1])*Ledge[1];
								physin[2] = ((float) in[2] + 
												 (0.5 + (float) kk)/SeedPerV[2])*Ledge[2];

								len_back = TrackIt(coorded, in, physin, Ledge, Dim, 
														 MinFA, MaxAng, ArrMax, Tback, 
														 flTback, -1, phys_back);
            
								KEEPIT = 0; // a simple switch

								totlen = len_forw+len_back-1; // NB: overlap of starts
								totlen_phys = phys_forw[0] + phys_back[0];
		
								if( totlen_phys >= MinL ) {
		  
									// glue together for simpler notation later
									for( n=0 ; n<len_back ; n++) { // all of this
										rr = len_back-n-1; // read in backward
										for(m=0;m<3;m++)
											Ttot[rr][m] = Tback[n][m];
									}
									for( n=1 ; n<len_forw ; n++){// skip first->overlap
										rr = n+len_back-1; // put after
										for(m=0;m<3;m++)
											Ttot[rr][m] = Tforw[n][m];
									}
									// <<So close and orthogonal condition>>:
									// test projecting ends, to see if they abut ROI.  
									for(m=0;m<3;m++) { 
										//actual projected ends
										end[1][m] = 2*Ttot[totlen-1][m]-Ttot[totlen-2][m];
										end[0][m] = 2*Ttot[0][m]-Ttot[1][m];
										// default choice, just retest known ends 
										// as default
										test_ind[1][m] = test_ind[0][m] = Ttot[0][m];
									}
		  
									tt = Create_Tract(len_back, flTback, len_forw, 
															flTforw, id, insetFA); ++id; 
        
									if (LOG_TYPE == -1) {
										KEEPIT = 1; 
									} else {
										inroi1 = 0;
										// check forw
										for( n=0 ; n<len_forw ; n++) {
											if(INDEX[Tforw[n][0]][Tforw[n][1]][Tforw[n][2]][1]==1){
												inroi1 = 1;
												break;
											} else
												continue;
										}
										if( inroi1==0 ){// after 1st half, check 2nd half
											for( m=0 ; m<len_back ; m++) {
												if(INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][1]==1){
													inroi1 = 1;
													break;
												} else
													continue;
											}
										}
										// after 1st&2nd halves, check bound/neigh
										if( inroi1==0 ) {
											if(INDEX[test_ind[1][0]][test_ind[1][1]][test_ind[1][2]][1]==1)
												inroi1 = 1;
											if(INDEX[test_ind[0][0]][test_ind[0][1]][test_ind[0][2]][1]==1)
												inroi1 = 1;
										}
			 
										if( ((LOG_TYPE ==0) && (inroi1 ==0)) || 
											 ((LOG_TYPE ==1) && (inroi1 ==1))) {
											// have to check in ROI2
				
											inroi2 = 0;
											// check forw
											for( n=0 ; n<len_forw ; n++) {
												if(INDEX[Tforw[n][0]][Tforw[n][1]][Tforw[n][2]][2]==1){
													inroi2 = 1;
													break;
												} else
													continue;
											}
											//after 1st half, check 2nd half
											if( inroi2==0 ) { 
												for( m=0 ; m<len_back ; m++) {
													if(INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][2]==1){
														inroi2 = 1;
														break;
													} else
														continue;
												}
											}
											// after 1st&2nd halves, check bound/neigh
											if( inroi2==0 ) { 
												if(INDEX[test_ind[1][0]][test_ind[1][1]][test_ind[1][2]][2]==1)
													inroi2 = 1;
												if(INDEX[test_ind[0][0]][test_ind[0][1]][test_ind[0][2]][2]==1)
													inroi2 = 1;
											}
				
											// for both cases, need to see it here to keep
											if( inroi2 ==1 )
												KEEPIT = 1; // otherwise, it's gone
				
										} else if((LOG_TYPE ==0) && (inroi1 ==1))
											KEEPIT = 1;
									}
								}
      
								// by now, we *know* if we're keeping this or not.
								if( KEEPIT == 1 ) {
									tb = AppCreateBundle(tb, 1, tt, NULL); 
									tt = Free_Tracts(tt, 1);
        
									READS_in = totlen;
									fwrite(&READS_in,sizeof(READS_in),1,fout0);
									for( n=0 ; n<len_back ; n++) {
										//put this one in backwords, to make it connect
										m = len_back - 1 - n; 
										for(aa=0 ; aa<3 ; aa++) {
											// recenter phys loc for trackvis, if nec...
											// just works this way (where they define 
											// origin)
											READS_fl = flTback[m][aa];
											if(!TV_switch[aa])
												READS_fl = Ledge[aa]*Dim[aa]-READS_fl;
											fwrite(&READS_fl,sizeof(READS_fl),1,fout0);
										}
										mm = INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][0];
										READS_fl =THD_get_voxel(insetFA, mm, 0); // FA
										fwrite(&READS_fl,sizeof(READS_fl),1,fout0);
										READS_fl =THD_get_voxel(insetMD, mm, 0); // MD
										fwrite(&READS_fl,sizeof(READS_fl),1,fout0);
										READS_fl =THD_get_voxel(insetL1, mm, 0); // L1
										fwrite(&READS_fl,sizeof(READS_fl),1,fout0);
										// count this voxel for having a tract
										INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][3]+= 1; 
									}
        
									for( m=1 ; m<len_forw ; m++) {
										for(aa=0 ; aa<3 ; aa++) {
											// recenter phys loc for trackvis, if nec...
											READS_fl = flTforw[m][aa];
											if(!TV_switch[aa])
												READS_fl = Ledge[aa]*Dim[aa]-READS_fl;
											fwrite(&READS_fl,sizeof(READS_fl),1,fout0);
										}
										mm = INDEX[Tforw[m][0]][Tforw[m][1]][Tforw[m][2]][0];
										READS_fl =THD_get_voxel(insetFA, mm, 0); // FA
										fwrite(&READS_fl,sizeof(READS_fl),1,fout0);
										READS_fl =THD_get_voxel(insetMD, mm, 0); // MD
										fwrite(&READS_fl,sizeof(READS_fl),1,fout0);
										READS_fl =THD_get_voxel(insetL1, mm, 0); // L1 
										fwrite(&READS_fl,sizeof(READS_fl),1,fout0);
										// count this voxel for having a tract
										INDEX[Tforw[m][0]][Tforw[m][1]][Tforw[m][2]][3]+= 1; 
									}
        
									ave_tract_len+= totlen;
									ave_tract_len_phys+= totlen_phys;
									Numtract+=1;
								}   
							}
				}
	fclose(fout0); 
  
	if (get_tract_verb()) {
		INFO_message("Done tracking, have %d tracks.", tb->N_tracts);
		Show_Taylor_Bundle(tb, NULL, 3);
	}

	if (!Write_Bundle(tb,prefix,mode)) {
		ERROR_message("Failed to write the bundle");
	}
   
	// **************************************************************
	// **************************************************************
	//                    Some simple stats on ROIs and outputs
	// **************************************************************
	// **************************************************************

	for( k=0 ; k<Dim[2] ; k++ ) 
		for( j=0 ; j<Dim[1] ; j++ ) 
			for( i=0 ; i<Dim[0] ; i++ ) {
				if( INDEX[i][j][k][3]>=1 ) {
					tempMD = THD_get_voxel(insetMD,INDEX[i][j][k][0],0);
					tempFA = THD_get_voxel(insetFA,INDEX[i][j][k][0],0);
					tempL1 = THD_get_voxel(insetL1,INDEX[i][j][k][0],0);
					tempRD = 0.5*(3*tempMD-tempL1);
					roi3_mu_MD+= tempMD;
					roi3_mu_FA+= tempFA;
					roi3_mu_L1+= tempL1;
					roi3_mu_RD+= tempRD;
					roi3_sd_MD+= tempMD*tempMD;
					roi3_sd_FA+= tempFA*tempFA;
					roi3_sd_L1+= tempL1*tempL1;
					roi3_sd_RD+= tempRD*tempRD;
					roi3_ct+= 1;
				}
			}
  
	if(roi3_ct > 0 ) { // !!!! make into afni file
		roi3_mu_MD/= (float) roi3_ct; 
		roi3_mu_FA/= (float) roi3_ct;
		roi3_mu_L1/= (float) roi3_ct;
		roi3_mu_RD/= (float) roi3_ct;
    
		roi3_sd_MD-= roi3_ct*roi3_mu_MD*roi3_mu_MD;
		roi3_sd_FA-= roi3_ct*roi3_mu_FA*roi3_mu_FA;
		roi3_sd_L1-= roi3_ct*roi3_mu_L1*roi3_mu_L1;
		roi3_sd_RD-= roi3_ct*roi3_mu_RD*roi3_mu_RD;
		roi3_sd_MD/= (float) roi3_ct-1; 
		roi3_sd_FA/= (float) roi3_ct-1;
		roi3_sd_L1/= (float) roi3_ct-1;
		roi3_sd_RD/= (float) roi3_ct-1;
		roi3_sd_MD = sqrt(roi3_sd_MD); 
		roi3_sd_FA = sqrt(roi3_sd_FA);
		roi3_sd_L1 = sqrt(roi3_sd_L1);
		roi3_sd_RD = sqrt(roi3_sd_RD);
  
		sprintf(OUT_tracstat,"%s.stats",prefix);
		if( (fout0 = fopen(OUT_tracstat, "w")) == NULL) {
			fprintf(stderr, "Error opening file %s.",OUT_tracstat);
			exit(19);
		}
		fprintf(fout0,"%d\t%d\n",Numtract,roi3_ct);
		fprintf(fout0,"%.3f\t%.3f\n",ave_tract_len/Numtract,
				  ave_tract_len_phys/Numtract);
		// as usual, these next values would have to be divided by the
		// bval to get their actual value in standard phys units
		fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_FA,roi3_sd_FA);
		fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_MD,roi3_sd_MD);
		fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_RD,roi3_sd_RD);
		fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_L1,roi3_sd_L1);
		fclose(fout0);

		sprintf(prefix_map,"%s_MAP",prefix); 
		sprintf(prefix_mask,"%s_MASK",prefix); 

		outsetMAP = EDIT_empty_copy( mset1 ) ;
		EDIT_dset_items( outsetMAP ,
							  ADN_datum_all , MRI_short , 
							  ADN_prefix    , prefix_map ,
							  ADN_none ) ;
		if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMAP)) )
			ERROR_exit("Can't overwrite existing dataset '%s'",
						  DSET_HEADNAME(outsetMAP));
    
		outsetMASK = EDIT_empty_copy( mset1 ) ;
		EDIT_dset_items( outsetMASK ,
							  ADN_datum_all , MRI_byte , 
							  ADN_prefix    , prefix_mask ,
							  ADN_none ) ;
		if(!THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMASK)) )
			ERROR_exit("Can't overwrite existing dataset '%s'",
						  DSET_HEADNAME(outsetMASK));
    
		m=0;
		for( k=0 ; k<Dim[2] ; k++ ) 
			for( j=0 ; j<Dim[1] ; j++ ) 
				for( i=0 ; i<Dim[0] ; i++ ) {
					temp_arr[m]=INDEX[i][j][k][3];
					if(temp_arr[m]>0.5)
						temp_byte[m]=1;
					else
						temp_byte[m]=0;
					m++;
				}
    
		// re-orient the data as original inputs 
		// (this function copies the pointer)
		EDIT_substitute_brick(outsetMAP, 0, MRI_short, temp_arr); 
		temp_arr=NULL;
		if(TV_switch[0] || TV_switch[1] || TV_switch[2]) {
			dsetn = r_new_resam_dset(outsetMAP, NULL, 0.0, 0.0, 0.0,
											 header1.voxel_order, RESAM_NN_TYPE, 
											 NULL, 1, 0);
			DSET_delete(outsetMAP); 
			outsetMAP=dsetn;
			dsetn=NULL;
		}
		EDIT_dset_items( outsetMAP ,
							  ADN_prefix , prefix_map ,
							  ADN_none ) ;
		THD_load_statistics(outsetMAP );
		if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMAP)) )
			ERROR_exit("Can't overwrite existing dataset '%s'",
						  DSET_HEADNAME(outsetMAP));
		tross_Make_History( "3dTrackID" , argc , argv ,  outsetMAP) ;
		THD_write_3dim_dataset(NULL, NULL, outsetMAP, True);
		// re-orient the data as original inputs
		EDIT_substitute_brick(outsetMASK, 0, MRI_byte, temp_byte);
		temp_byte=NULL;
		if(TV_switch[0] || TV_switch[1] || TV_switch[2]) {
			dsetn = r_new_resam_dset(outsetMASK, NULL, 0.0, 0.0, 0.0,
											 header1.voxel_order, RESAM_NN_TYPE, 
											 NULL, 1, 0);
			DSET_delete(outsetMASK); 
			outsetMASK=dsetn;
			dsetn=NULL;
		}
		EDIT_dset_items( outsetMASK ,
							  ADN_prefix , prefix_mask ,
							  ADN_none ) ;
		THD_load_statistics(outsetMASK);
		if(!THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMASK)) )
			ERROR_exit("Can't overwrite existing dataset '%s'",
						  DSET_HEADNAME(outsetMASK));
		tross_Make_History( "3dTrackID" , argc , argv ,  outsetMASK) ;
		THD_write_3dim_dataset(NULL, NULL, outsetMASK, True);

		INFO_message("Number of tracts found = %d",Numtract) ;
	}
	else 
		INFO_message("\n No Tracts Found!!!\n");
  

	// ************************************************************
	// ************************************************************
	//                    Freeing
	// ************************************************************
	// ************************************************************

	// !!! need to free afni-sets?
	DSET_delete(insetFA);
	DSET_delete(insetMD);
	DSET_delete(insetL1);
	DSET_delete(insetV1);
	DSET_delete(insetEXTRA);
	//DSET_delete(outsetMAP);  
	//DSET_delete(outsetMASK);
	DSET_delete(mset2);
	DSET_delete(mset1);

	free(prefix);
	free(insetV1);
	free(insetFA);
	free(mset1);
	free(mset2);
  	free(insetEXTRA);

	free(ROI1);
	free(ROI2);
	free(temp_byte);
  
	for( i=0 ; i<ArrMax ; i++) {
		free(Tforw[i]);
		free(Tback[i]);
		free(flTforw[i]);
		free(flTback[i]);
	}
	free(Tforw);
	free(Tback);
	free(flTforw);
	free(flTback);
  
	for( i=0 ; i<Dim[0] ; i++) 
		for( j=0 ; j<Dim[1] ; j++) 
			for( k=0 ; k<Dim[2] ; k++) 
				free(coorded[i][j][k]);
	for( i=0 ; i<Dim[0] ; i++) 
		for( j=0 ; j<Dim[1] ; j++) 
			free(coorded[i][j]);
	for( i=0 ; i<Dim[0] ; i++) 
		free(coorded[i]);
	free(coorded);

	for( i=0 ; i<Dim[0] ; i++) 
		for( j=0 ; j<Dim[1] ; j++) 
			for( k=0 ; k<Dim[2] ; k++) 
				free(INDEX[i][j][k]);
	for( i=0 ; i<Dim[0] ; i++) 
		for( j=0 ; j<Dim[1] ; j++) 
			free(INDEX[i][j]);
	for( i=0 ; i<Dim[0] ; i++) 
		free(INDEX[i]);
	free(INDEX);

	free(temp_arr); // need to free
	for( i=0 ; i<2*ArrMax ; i++) 
		free(Ttot[i]);
	free(Ttot);

	//free(mode);
	
	return 0;
}