Exemplo n.º 1
0
void THD_load_tcat( THD_datablock *dblk )
{
   int ivout , dd , iv ;
   THD_3dim_dataset *dset_in , *dset_out ;
   NI_str_array *sar ;

ENTRY("THD_load_tcat") ;

   if( !ISVALID_DBLK(dblk) ) EXRETURN ;
   dset_out = (THD_3dim_dataset *)dblk->parent ;
   if( !ISVALID_DSET(dset_out) ) EXRETURN ;
   sar = NI_decode_string_list( dset_out->tcat_list , "~" ) ;
   if( sar == NULL ) EXRETURN ;
   if( sar->num != dset_out->tcat_num ){ NI_delete_str_array(sar); EXRETURN; }

   ivout = 0 ;
   for( dd=0 ; dd < sar->num ; dd++ ){
     dset_in = THD_open_dataset( sar->str[dd] ) ;
     if( dset_in == NULL ){
       NI_delete_str_array(sar) ; DSET_unload(dset_out) ;
       EXRETURN ;
     }
     DSET_mallocize(dset_in) ; DSET_load(dset_in) ;
     if( !DSET_LOADED(dset_in) ){
       NI_delete_str_array(sar) ; DSET_unload(dset_out) ; DSET_delete(dset_in) ;
       EXRETURN ;
     }

     for( iv=0 ; iv < DSET_NVALS(dset_in) ; iv++ ){
       EDIT_substitute_brick( dset_out , ivout ,
                              DSET_BRICK_TYPE(dset_in,iv), DSET_ARRAY(dset_in,iv) );
       mri_fix_data_pointer( NULL , DSET_BRICK(dset_in,iv) ) ;
       EDIT_BRICK_FACTOR( dset_out , ivout , DSET_BRICK_FACTOR(dset_in,iv) ) ;
       EDIT_BRICK_LABEL(dset_out, ivout, 
                        DSET_BRICK_LABEL(dset_in, iv)); /* ZSS Aug. 27 2012 */
       ivout++ ;
     }
     DSET_delete(dset_in) ;
   }

   NI_delete_str_array(sar) ; EXRETURN ;
}
Exemplo n.º 2
0
THD_3dim_dataset * THD_despike9_dataset( THD_3dim_dataset *inset , byte *mask )
{
   THD_3dim_dataset *outset ;
   MRI_vectim *mrv ;
   int ii ;

ENTRY("THD_despike9_dataset") ;

   if( !ISVALID_DSET(inset) || DSET_NVALS(inset) < 9 ) RETURN(NULL) ;

   mrv = THD_dset_to_vectim(inset,mask,0) ;  DSET_unload(inset) ;
   if( mrv == NULL ) RETURN(NULL) ;

   (void)THD_vectim_despike9(mrv) ;

   outset = EDIT_empty_copy(inset) ;
   for( ii=0 ; ii < DSET_NVALS(outset) ; ii++ )
     EDIT_substitute_brick(outset,ii,MRI_float,NULL) ;

   THD_vectim_to_dset(mrv,outset) ; VECTIM_destroy(mrv) ;
   RETURN(outset) ;
}
Exemplo n.º 3
0
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *yset=NULL , *aset=NULL , *mset=NULL , *wset=NULL ;
   MRI_IMAGE *fim=NULL, *qim,*tim, *pfim=NULL , *vim     , *wim=NULL  ;
   float     *flar    , *qar,*tar, *par=NULL  , *var     , *war=NULL  ;
   MRI_IMARR *fimar=NULL ;
   MRI_IMAGE *aim , *yim ; float *aar , *yar ;
   int nt=0 , nxyz=0 , nvox=0 , nparam=0 , nqbase , polort=0 , ii,jj,kk,bb ;
   byte *mask=NULL ; int nmask=0 , iarg ;
   char *fname_out="-" ;   /** equiv to stdout **/

   float alpha=0.0f ;
   int   nfir =0 ; float firwt[5]={0.09f,0.25f,0.32f,0.25f,0.09f} ;
   int   nmed =0 ;
   int   nwt  =0 ;

#define METHOD_C  3
#define METHOD_K 11
   int   method = METHOD_C ;

   /**--- help the pitiful user? ---**/

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
     printf(
      "Usage: 3dInvFMRI [options]\n"
      "Program to compute stimulus time series, given a 3D+time dataset\n"
      "and an activation map (the inverse of the usual FMRI analysis problem).\n"
      "-------------------------------------------------------------------\n"
      "OPTIONS:\n"
      "\n"
      " -data yyy  =\n"
      "   *OR*     = Defines input 3D+time dataset [a non-optional option].\n"
      " -input yyy =\n"
      "\n"
      " -map  aaa  = Defines activation map; 'aaa' should be a bucket dataset,\n"
      "                each sub-brick of which defines the beta weight map for\n"
      "                an unknown stimulus time series [also non-optional].\n"
      "\n"
      " -mapwt www = Defines a weighting factor to use for each element of\n"
      "                the map.  The dataset 'www' can have either 1 sub-brick,\n"
      "                or the same number as in the -map dataset.  In the\n"
      "                first case, in each voxel, each sub-brick of the map\n"
      "                gets the same weight in the least squares equations.\n"
      "                  [default: all weights are 1]\n"
      "\n"
      " -mask mmm  = Defines a mask dataset, to restrict input voxels from\n"
      "                -data and -map.  [default: all voxels are used]\n"
      "\n"
      " -base fff  = Each column of the 1D file 'fff' defines a baseline time\n"
      "                series; these columns should be the same length as\n"
      "                number of time points in 'yyy'.  Multiple -base options\n"
      "                can be given.\n"
      " -polort pp = Adds polynomials of order 'pp' to the baseline collection.\n"
      "                The default baseline model is '-polort 0' (constant).\n"
      "                To specify no baseline model at all, use '-polort -1'.\n"
      "\n"
      " -out vvv   = Name of 1D output file will be 'vvv'.\n"
      "                [default = '-', which is stdout; probably not good]\n"
      "\n"
      " -method M  = Determines the method to use.  'M' is a single letter:\n"
      "               -method C = least squares fit to data matrix Y [default]\n"
      "               -method K = least squares fit to activation matrix A\n"
      "\n"
      " -alpha aa  = Set the 'alpha' factor to 'aa'; alpha is used to penalize\n"
      "                large values of the output vectors.  Default is 0.\n"
      "                A large-ish value for alpha would be 0.1.\n"
      "\n"
      " -fir5     = Smooth the results with a 5 point lowpass FIR filter.\n"
      " -median5  = Smooth the results with a 5 point median filter.\n"
      "               [default: no smoothing; only 1 of these can be used]\n"
      "-------------------------------------------------------------------\n"
      "METHODS:\n"
      " Formulate the problem as\n"
      "    Y = V A' + F C' + errors\n"
      " where Y = data matrix      (N x M) [from -data]\n"
      "       V = stimulus         (N x p) [to -out]\n"
      "       A = map matrix       (M x p) [from -map]\n"
      "       F = baseline matrix  (N x q) [from -base and -polort]\n"
      "       C = baseline weights (M x q) [not computed]\n"
      "       N = time series length = length of -data file\n"
      "       M = number of voxels in mask\n"
      "       p = number of stimulus time series to estimate\n"
      "         = number of parameters in -map file\n"
      "       q = number of baseline parameters\n"
      "   and ' = matrix transpose operator\n"
      " Next, define matrix Z (Y detrended relative to columns of F) by\n"
      "                       -1\n"
      "   Z = [I - F(F'F)  F']  Y\n"
      "-------------------------------------------------------------------\n"
      " The method C solution is given by\n"
      "                 -1\n"
      "   V0 = Z A [A'A]\n"
      "\n"
      " This solution minimizes the sum of squares over the N*M elements\n"
      " of the matrix   Y - V A' + F C'   (N.B.: A' means A-transpose).\n"
      "-------------------------------------------------------------------\n"
      " The method K solution is given by\n"
      "             -1                            -1\n"
      "   W = [Z Z']  Z A   and then   V = W [W'W]\n"
      "\n"
      " This solution minimizes the sum of squares of the difference between\n"
      " the A(V) predicted from V and the input A, where A(V) is given by\n"
      "                    -1\n"
      "   A(V) = Z' V [V'V]   = Z'W\n"
      "-------------------------------------------------------------------\n"
      " Technically, the solution is unidentfiable up to an arbitrary\n"
      " multiple of the columns of F (i.e., V = V0 + F G, where G is\n"
      " an arbitrary q x p matrix); the solution above is the solution\n"
      " that is orthogonal to the columns of F.\n"
      "\n"
      "-- RWCox - March 2006 - purely for experimental purposes!\n"
     ) ;

     printf("\n"
     "===================== EXAMPLE USAGE =====================================\n"
     "** Step 1: From a training dataset, generate activation map.\n"
     "  The input dataset has 4 runs, each 108 time points long.  3dDeconvolve\n"
     "  is used on the first 3 runs (time points 0..323) to generate the\n"
     "  activation map.  There are two visual stimuli (Complex and Simple).\n"
     "\n"
     "  3dDeconvolve -x1D xout_short_two.1D -input rall_vr+orig'[0..323]'   \\\n"
     "      -num_stimts 2                                                   \\\n"
     "      -stim_file 1 hrf_complex.1D               -stim_label 1 Complex \\\n"
     "      -stim_file 2 hrf_simple.1D                -stim_label 2 Simple  \\\n"
     "      -concat '1D:0,108,216'                                          \\\n"
     "      -full_first -fout -tout                                         \\\n"
     "      -bucket func_ht2_short_two -cbucket cbuc_ht2_short_two\n"
     "\n"
     "  N.B.: You may want to de-spike, smooth, and register the 3D+time\n"
     "        dataset prior to the analysis (as usual).  These steps are not\n"
     "        shown here -- I'm presuming you know how to use AFNI already.\n"
     "\n"
     "** Step 2: Create a mask of highly activated voxels.\n"
     "  The F statistic threshold is set to 30, corresponding to a voxel-wise\n"
     "  p = 1e-12 = very significant.  The mask is also lightly clustered, and\n"
     "  restricted to brain voxels.\n"
     "\n"
     "  3dAutomask -prefix Amask rall_vr+orig\n"
     "  3dcalc -a 'func_ht2_short+orig[0]' -b Amask+orig -datum byte \\\n"
     "         -nscale -expr 'step(a-30)*b' -prefix STmask300\n"
     "  3dmerge -dxyz=1 -1clust 1.1 5 -prefix STmask300c STmask300+orig\n"
     "\n"
     "** Step 3: Run 3dInvFMRI to estimate the stimulus functions in run #4.\n"
     "  Run #4 is time points 324..431 of the 3D+time dataset (the -data\n"
     "  input below).  The -map input is the beta weights extracted from\n"
     "  the -cbucket output of 3dDeconvolve.\n"
     "\n"
     "  3dInvFMRI -mask STmask300c+orig                       \\\n"
     "            -data rall_vr+orig'[324..431]'              \\\n"
     "            -map cbuc_ht2_short_two+orig'[6..7]'        \\\n"
     "            -polort 1 -alpha 0.01 -median5 -method K    \\\n"
     "            -out ii300K_short_two.1D\n"
     "\n"
     "  3dInvFMRI -mask STmask300c+orig                       \\\n"
     "            -data rall_vr+orig'[324..431]'              \\\n"
     "            -map cbuc_ht2_short_two+orig'[6..7]'        \\\n"
     "            -polort 1 -alpha 0.01 -median5 -method C    \\\n"
     "            -out ii300C_short_two.1D\n"
     "\n"
     "** Step 4: Plot the results, and get confused.\n"
     "\n"
     "  1dplot -ynames VV KK CC -xlabel Run#4 -ylabel ComplexStim \\\n"
     "         hrf_complex.1D'{324..432}'                         \\\n"
     "         ii300K_short_two.1D'[0]'                           \\\n"
     "         ii300C_short_two.1D'[0]'\n"
     "\n"
     "  1dplot -ynames VV KK CC -xlabel Run#4 -ylabel SimpleStim \\\n"
     "         hrf_simple.1D'{324..432}'                         \\\n"
     "         ii300K_short_two.1D'[1]'                          \\\n"
     "         ii300C_short_two.1D'[1]'\n"
     "\n"
     "  N.B.: I've found that method K works better if MORE voxels are\n"
     "        included in the mask (lower threshold) and method C if\n"
     "        FEWER voxels are included.  The above threshold gave 945\n"
     "        voxels being used to determine the 2 output time series.\n"
     "=========================================================================\n"
     ) ;

     PRINT_COMPILE_DATE ; exit(0) ;
   }

   /**--- bureaucracy ---**/

   mainENTRY("3dInvFMRI main"); machdep();
   PRINT_VERSION("3dInvFMRI"); AUTHOR("Zhark");
   AFNI_logger("3dInvFMRI",argc,argv) ;

   /**--- scan command line ---**/

   iarg = 1 ;
   while( iarg < argc ){

     if( strcmp(argv[iarg],"-method") == 0 ){
       switch( argv[++iarg][0] ){
         default:
           WARNING_message("Ignoring illegal -method '%s'",argv[iarg]) ;
         break ;
         case 'C': method = METHOD_C ; break ;
         case 'K': method = METHOD_K ; break ;
       }
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-fir5") == 0 ){
       if( nmed > 0 ) WARNING_message("Ignoring -fir5 in favor of -median5") ;
       else           nfir = 5 ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-median5") == 0 ){
       if( nfir > 0 ) WARNING_message("Ignoring -median5 in favor of -fir5") ;
       else           nmed = 5 ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-alpha") == 0 ){
       alpha = (float)strtod(argv[++iarg],NULL) ;
       if( alpha <= 0.0f ){
         alpha = 0.0f ; WARNING_message("-alpha '%s' ignored!",argv[iarg]) ;
       }
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-data") == 0 || strcmp(argv[iarg],"-input") == 0 ){
       if( yset != NULL ) ERROR_exit("Can't input 2 3D+time datasets") ;
       yset = THD_open_dataset(argv[++iarg]) ;
       CHECK_OPEN_ERROR(yset,argv[iarg]) ;
       nt = DSET_NVALS(yset) ;
       if( nt < 2 ) ERROR_exit("Only 1 sub-brick in dataset %s",argv[iarg]) ;
       nxyz = DSET_NVOX(yset) ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-map") == 0 ){
       if( aset != NULL ) ERROR_exit("Can't input 2 -map datasets") ;
       aset = THD_open_dataset(argv[++iarg]) ;
       CHECK_OPEN_ERROR(aset,argv[iarg]) ;
       nparam = DSET_NVALS(aset) ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-mapwt") == 0 ){
       if( wset != NULL ) ERROR_exit("Can't input 2 -mapwt datasets") ;
       wset = THD_open_dataset(argv[++iarg]) ;
       CHECK_OPEN_ERROR(wset,argv[iarg]) ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-mask") == 0 ){
       if( mset != NULL ) ERROR_exit("Can't input 2 -mask datasets") ;
       mset = THD_open_dataset(argv[++iarg]) ;
       CHECK_OPEN_ERROR(mset,argv[iarg]) ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-polort") == 0 ){
       char *cpt ;
       polort = (int)strtod(argv[++iarg],&cpt) ;
       if( *cpt != '\0' ) WARNING_message("Illegal non-numeric value after -polort") ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-out") == 0 ){
       fname_out = strdup(argv[++iarg]) ;
       if( !THD_filename_ok(fname_out) )
         ERROR_exit("Bad -out filename '%s'",fname_out) ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-base") == 0 ){
       if( fimar == NULL ) INIT_IMARR(fimar) ;
       qim = mri_read_1D( argv[++iarg] ) ;
       if( qim == NULL ) ERROR_exit("Can't read 1D file %s",argv[iarg]) ;
       ADDTO_IMARR(fimar,qim) ;
       iarg++ ; continue ;
     }

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

   /**--- finish up processing options ---**/

   if( yset == NULL ) ERROR_exit("No input 3D+time dataset?!") ;
   if( aset == NULL ) ERROR_exit("No input FMRI -map dataset?!") ;

   if( DSET_NVOX(aset) != nxyz )
     ERROR_exit("Grid mismatch between -data and -map") ;

   INFO_message("Loading dataset for Y") ;
   DSET_load(yset); CHECK_LOAD_ERROR(yset) ;
   INFO_message("Loading dataset for A") ;
   DSET_load(aset); CHECK_LOAD_ERROR(aset) ;

   if( wset != NULL ){
     if( DSET_NVOX(wset) != nxyz )
       ERROR_exit("Grid mismatch between -data and -mapwt") ;
     nwt = DSET_NVALS(wset) ;
     if( nwt > 1 && nwt != nparam )
       ERROR_exit("Wrong number of values=%d in -mapwt; should be 1 or %d",
                  nwt , nparam ) ;
     INFO_message("Loading dataset for mapwt") ;
     DSET_load(wset); CHECK_LOAD_ERROR(wset) ;
   }

   if( mset != NULL ){
     if( DSET_NVOX(mset) != nxyz )
       ERROR_exit("Grid mismatch between -data and -mask") ;
     INFO_message("Loading dataset for mask") ;
     DSET_load(mset); CHECK_LOAD_ERROR(mset) ;
     mask  = THD_makemask( mset , 0 , 1.0f,-1.0f ); DSET_delete(mset);
     nmask = THD_countmask( nxyz , mask ) ;
     if( nmask < 3 ){
       WARNING_message("Mask has %d voxels -- ignoring!",nmask) ;
       free(mask) ; mask = NULL ; nmask = 0 ;
     }
   }

   nvox = (nmask > 0) ? nmask : nxyz ;
   INFO_message("N = time series length  = %d",nt    ) ;
   INFO_message("M = number of voxels    = %d",nvox  ) ;
   INFO_message("p = number of params    = %d",nparam) ;

   /**--- set up baseline funcs in one array ---*/

   nqbase = (polort >= 0 ) ? polort+1 : 0 ;
   if( fimar != NULL ){
     for( kk=0 ; kk < IMARR_COUNT(fimar) ; kk++ ){
       qim = IMARR_SUBIMAGE(fimar,kk) ;
       if( qim != NULL && qim->nx != nt )
         WARNING_message("-base #%d length=%d; data length=%d",kk+1,qim->nx,nt) ;
       nqbase += qim->ny ;
     }
   }

   INFO_message("q = number of baselines = %d",nqbase) ;

#undef  F
#define F(i,j) flar[(i)+(j)*nt]   /* nt X nqbase */
   if( nqbase > 0 ){
     fim  = mri_new( nt , nqbase , MRI_float ) ;   /* F matrix */
     flar = MRI_FLOAT_PTR(fim) ;
     bb = 0 ;
     if( polort >= 0 ){                /** load polynomial baseline **/
       double a = 2.0/(nt-1.0) ;
       for( jj=0 ; jj <= polort ; jj++ ){
         for( ii=0 ; ii < nt ; ii++ )
           F(ii,jj) = (float)Plegendre( a*ii-1.0 , jj ) ;
       }
       bb = polort+1 ;
     }
#undef  Q
#define Q(i,j) qar[(i)+(j)*qim->nx]  /* qim->nx X qim->ny */

     if( fimar != NULL ){             /** load -base baseline columns **/
       for( kk=0 ; kk < IMARR_COUNT(fimar) ; kk++ ){
         qim = IMARR_SUBIMAGE(fimar,kk) ; qar = MRI_FLOAT_PTR(qim) ;
         for( jj=0 ; jj < qim->ny ; jj++ ){
           for( ii=0 ; ii < nt ; ii++ )
             F(ii,bb+jj) = (ii < qim->nx) ? Q(ii,jj) : 0.0f ;
         }
         bb += qim->ny ;
       }
       DESTROY_IMARR(fimar) ; fimar=NULL ;
     }

     /* remove mean from each column after first? */

     if( polort >= 0 && nqbase > 1 ){
       float sum ;
       for( jj=1 ; jj < nqbase ; jj++ ){
         sum = 0.0f ;
         for( ii=0 ; ii < nt ; ii++ ) sum += F(ii,jj) ;
         sum /= nt ;
         for( ii=0 ; ii < nt ; ii++ ) F(ii,jj) -= sum ;
       }
     }

     /* compute pseudo-inverse of baseline matrix,
        so we can project it out from the data time series */

     /*      -1          */
     /* (F'F)  F' matrix */

     INFO_message("Computing pseudo-inverse of baseline matrix F") ;
     pfim = mri_matrix_psinv(fim,NULL,0.0f) ; par = MRI_FLOAT_PTR(pfim) ;

#undef  P
#define P(i,j) par[(i)+(j)*nqbase]   /* nqbase X nt */

#if 0
     qim = mri_matrix_transpose(pfim) ;    /** save to disk? **/
     mri_write_1D( "Fpsinv.1D" , qim ) ;
     mri_free(qim) ;
#endif
   }

   /**--- set up map image into aim/aar = A matrix ---**/

#undef  GOOD
#define GOOD(i) (mask==NULL || mask[i])

#undef  A
#define A(i,j) aar[(i)+(j)*nvox]   /* nvox X nparam */

   INFO_message("Loading map matrix A") ;
   aim = mri_new( nvox , nparam , MRI_float ); aar = MRI_FLOAT_PTR(aim);
   for( jj=0 ; jj < nparam ; jj++ ){
     for( ii=kk=0 ; ii < nxyz ; ii++ ){
       if( GOOD(ii) ){ A(kk,jj) = THD_get_voxel(aset,ii,jj); kk++; }
   }}
   DSET_unload(aset) ;

   /**--- set up map weight into wim/war ---**/

#undef  WT
#define WT(i,j) war[(i)+(j)*nvox]   /* nvox X nparam */

   if( wset != NULL ){
     int numneg=0 , numpos=0 ;
     float fac ;

     INFO_message("Loading map weight matrix") ;
     wim = mri_new( nvox , nwt , MRI_float ) ; war = MRI_FLOAT_PTR(wim) ;
     for( jj=0 ; jj < nwt ; jj++ ){
       for( ii=kk=0 ; ii < nxyz ; ii++ ){
         if( GOOD(ii) ){
           WT(kk,jj) = THD_get_voxel(wset,ii,jj);
                if( WT(kk,jj) > 0.0f ){ numpos++; WT(kk,jj) = sqrt(WT(kk,jj)); }
           else if( WT(kk,jj) < 0.0f ){ numneg++; WT(kk,jj) = 0.0f;            }
           kk++;
         }
     }}
     DSET_unload(wset) ;
     if( numpos <= nparam )
       WARNING_message("Only %d positive weights found in -wtmap!",numpos) ;
     if( numneg > 0 )
       WARNING_message("%d negative weights found in -wtmap!",numneg) ;

     for( jj=0 ; jj < nwt ; jj++ ){
       fac = 0.0f ;
       for( kk=0 ; kk < nvox ; kk++ ) if( WT(kk,jj) > fac ) fac = WT(kk,jj) ;
       if( fac > 0.0f ){
         fac = 1.0f / fac ;
         for( kk=0 ; kk < nvox ; kk++ ) WT(kk,jj) *= fac ;
       }
     }
   }

   /**--- set up data image into yim/yar = Y matrix ---**/

#undef  Y
#define Y(i,j) yar[(i)+(j)*nt]   /* nt X nvox */

   INFO_message("Loading data matrix Y") ;
   yim = mri_new( nt , nvox , MRI_float ); yar = MRI_FLOAT_PTR(yim);
   for( ii=0 ; ii < nt ; ii++ ){
     for( jj=kk=0 ; jj < nxyz ; jj++ ){
       if( GOOD(jj) ){ Y(ii,kk) = THD_get_voxel(yset,jj,ii); kk++; }
   }}
   DSET_unload(yset) ;

   /**--- project baseline out of data image = Z matrix ---**/

   if( pfim != NULL ){
#undef  T
#define T(i,j) tar[(i)+(j)*nt]  /* nt X nvox */
     INFO_message("Projecting baseline out of Y") ;
     qim = mri_matrix_mult( pfim , yim ) ;   /* nqbase X nvox */
     tim = mri_matrix_mult(  fim , qim ) ;   /* nt X nvox */
     tar = MRI_FLOAT_PTR(tim) ;              /* Y projected onto baseline */
     for( jj=0 ; jj < nvox ; jj++ )
       for( ii=0 ; ii < nt ; ii++ ) Y(ii,jj) -= T(ii,jj) ;
     mri_free(tim); mri_free(qim); mri_free(pfim); mri_free(fim);
   }

   /***** At this point:
             matrix A is in aim,
             matrix Z is in yim.
          Solve for V into vim, using the chosen method *****/

   switch( method ){
     default: ERROR_exit("Illegal method code!  WTF?") ; /* Huh? */

     /*.....................................................................*/
     case METHOD_C:
       /**--- compute pseudo-inverse of A map ---**/

       INFO_message("Method C: Computing pseudo-inverse of A") ;
       if( wim != NULL ) WARNING_message("Ignoring -mapwt dataset") ;
       pfim = mri_matrix_psinv(aim,NULL,alpha) ;  /* nparam X nvox */
       if( pfim == NULL ) ERROR_exit("mri_matrix_psinv() fails") ;
       mri_free(aim) ;

       /**--- and apply to data to get results ---*/

       INFO_message("Computing result V") ;
       vim = mri_matrix_multranB( yim , pfim ) ; /* nt x nparam */
       mri_free(pfim) ; mri_free(yim) ;
     break ;

     /*.....................................................................*/
     case METHOD_K:
       /**--- compute pseudo-inverse of transposed Z ---*/

       INFO_message("Method K: Computing pseudo-inverse of Z'") ;
       if( nwt > 1 ){
         WARNING_message("Ignoring -mapwt dataset: more than 1 sub-brick") ;
         nwt = 0 ; mri_free(wim) ; wim = NULL ; war = NULL ;
       }

       if( nwt == 1 ){
         float fac ;
         for( kk=0 ; kk < nvox ; kk++ ){
           fac = war[kk] ;
           for( ii=0 ; ii < nt     ; ii++ ) Y(ii,kk) *= fac ;
           for( ii=0 ; ii < nparam ; ii++ ) A(kk,ii) *= fac ;
         }
       }

       tim  = mri_matrix_transpose(yim)        ; mri_free(yim) ;
       pfim = mri_matrix_psinv(tim,NULL,alpha) ; mri_free(tim) ;
       if( pfim == NULL ) ERROR_exit("mri_matrix_psinv() fails") ;

       INFO_message("Computing W") ;
       tim = mri_matrix_mult( pfim , aim ) ;
       mri_free(aim) ; mri_free(pfim) ;

       INFO_message("Computing result V") ;
       pfim = mri_matrix_psinv(tim,NULL,0.0f) ; mri_free(tim) ;
       vim  = mri_matrix_transpose(pfim)      ; mri_free(pfim);
     break ;

   } /* end of switch on method */

   if( wim != NULL ) mri_free(wim) ;

   /**--- smooth? ---**/

   if( nfir > 0 && vim->nx > nfir ){
     INFO_message("FIR-5-ing result") ;
     var = MRI_FLOAT_PTR(vim) ;
     for( jj=0 ; jj < vim->ny ; jj++ )
       linear_filter_reflect( nfir,firwt , vim->nx , var + (jj*vim->nx) ) ;
   }

   if( nmed > 0 && vim->nx > nmed ){
     INFO_message("Median-5-ing result") ;
     var = MRI_FLOAT_PTR(vim) ;
     for( jj=0 ; jj < vim->ny ; jj++ )
       median5_filter_reflect( vim->nx , var + (jj*vim->nx) ) ;
   }

   /**--- write results ---**/

   INFO_message("Writing result to '%s'",fname_out) ;
   mri_write_1D( fname_out , vim ) ;
   exit(0) ;
}
Exemplo n.º 4
0
int THD_conformist( int ndset, THD_3dim_dataset **dset, int flags , int *ijkpad )
{
   int iset , xpad_m,xpad_p , ypad_m,ypad_p , zpad_m,zpad_p , nwrit ;
   THD_dataxes *cx , *dx ;
   THD_3dim_dataset *qset ;
   int_pair pm ;
   int do_norefit = (flags & CONFORM_NOREFIT) ;
   int do_rewrite = (flags & CONFORM_REWRITE) && !do_norefit ;
   int do_ijkpad  = (ijkpad != NULL) ;

ENTRY("THD_conformist") ;

   /* check for good inputs */

   if( ndset <= 0 || dset == NULL ) RETURN(-1) ;
   for( iset=0 ; iset < ndset ; iset++ )
     if( !ISVALID_DSET(dset[iset]) ) RETURN(-2) ;

   /* check if all inputs are on the same grid (i.e., no work to do) */

   for( iset=1 ; iset < ndset ; iset++ ){
     if( ! EQUIV_DATAXES(dset[0]->daxes,dset[iset]->daxes) ) break ;
   }
   if( iset == ndset ){
     if( do_ijkpad ){
       for( iset=0 ; iset < 6*ndset ; iset++ ) ijkpad[iset] = 0 ;
     }
     RETURN(0) ;
   }

   /* construct the dataxes that encloses all the input datasets */

   cx = THD_superset_dataxes( dset[0]->daxes , dset[1]->daxes ) ;
   if( cx == NULL ){
     ERROR_message("3dConformist: '%s' and '%s' aren't compatible",
                   DSET_HEADNAME(dset[0]) , DSET_HEADNAME(dset[1]) ) ;
     RETURN(-3) ;
   }

   for( iset=2 ; iset < ndset ; iset++ ){
     dx = THD_superset_dataxes( cx , dset[iset]->daxes ) ;
     if( dx == NULL ){
       ERROR_message("3dConformist: '%s' is not compatible with others",
                     DSET_HEADNAME(dset[iset]) ) ;
       myXtFree(cx) ; RETURN(-3) ;
     }
     myXtFree(cx) ; cx = dx ; dx = NULL ;
   }

   /* now, re-create and re-write all datasets */

   if( do_rewrite )
     fprintf(stderr," + thd_conformist re-write loop: ") ;

   for( nwrit=iset=0 ; iset < ndset ; iset++ ){
     if( EQUIV_DATAXES(cx,dset[iset]->daxes) ){ /* already OK */
       if( do_rewrite ) fprintf(stderr,"-") ;
       if( do_ijkpad )
          ijkpad[6*iset+0] = ijkpad[6*iset+1] = ijkpad[6*iset+2]
        = ijkpad[6*iset+3] = ijkpad[6*iset+4] = ijkpad[6*iset+5] = 0 ;
       continue ;
     }
     pm = zpadax_pm( cx->nxx , cx->xxorg ,
                     dset[iset]->daxes->nxx , dset[iset]->daxes->xxorg ,
                     cx->xxdel ) ;
     xpad_m = pm.i ; xpad_p = pm.j ;
     pm = zpadax_pm( cx->nyy , cx->yyorg ,
                     dset[iset]->daxes->nyy , dset[iset]->daxes->yyorg ,
                     cx->yydel ) ;
     ypad_m = pm.i ; ypad_p = pm.j ;
     pm = zpadax_pm( cx->nzz , cx->zzorg ,
                     dset[iset]->daxes->nzz , dset[iset]->daxes->zzorg ,
                     cx->zzdel ) ;
     zpad_m = pm.i ; zpad_p = pm.j ;
     if( do_ijkpad ){
       ijkpad[6*iset+0] = xpad_m; ijkpad[6*iset+1] = xpad_p;
       ijkpad[6*iset+2] = ypad_m; ijkpad[6*iset+3] = ypad_p;
       ijkpad[6*iset+4] = zpad_m; ijkpad[6*iset+5] = zpad_p;
     }
     if( do_norefit ) continue ;   /* just wanted ijkpad, I guess */
     qset = THD_zeropad( dset[iset] ,
                         xpad_m,xpad_p , ypad_m,ypad_p , zpad_m,zpad_p ,
                         "BertieWooster" , ZPAD_PURGE | ZPAD_IJK ) ;
     if( qset == NULL ){  /* this should never happen */
       if( do_rewrite ) fprintf(stderr,"\n") ;
       ERROR_message("thd_conformist: skipping dataset %s",
                     DSET_HEADNAME(dset[iset])) ;
       continue ;
     }
     qset->idcode = dset[iset]->idcode ;
     EDIT_dset_items( qset , ADN_prefix , DSET_PREFIX(dset[iset]) , ADN_none ) ;
     if( do_rewrite ){
       THD_delete_3dim_dataset( dset[iset] , True ) ;
       DSET_overwrite(qset) ; DSET_unload(qset) ;
       fprintf(stderr,"+") ;
     } else {
       THD_delete_3dim_dataset( dset[iset] , False ) ;
     }
     dset[iset] = qset ; nwrit++ ;
   }
   if( do_rewrite ) fprintf(stderr,"\n") ;

   RETURN(nwrit) ;
}
Exemplo n.º 5
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 ;
   char *prefix="bandpass" ;
   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 ;

   /*-- help? --*/

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

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
     printf(
       "\n"
       "** NOTA BENE:  For the purpose of preparing resting-state FMRI datasets **\n"
       "** for analysis (e.g., with 3dGroupInCorr),  this program is now mostly **\n"
       "** superseded by the afni_proc.py script.  See the 'afni_proc.py -help' **\n"
       "** section 'Resting state analysis (modern)' to get our current rs-FMRI **\n"
       "** pre-processing recommended sequence of steps. -- RW Cox, et alii.    **\n"
       "\n"
       "Usage: 3dBandpass [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 3dBandpass 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"
       "* 3dBandpass 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 3dBandpass will\n"
       "   depend on the order in which you run these programs.  That's why\n"
       "   3dBandpass 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):\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"
       "\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.\n"
       " -quiet          = Turn off the fun and informative messages. (Why?)\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-voxel\n"
       "                      correlations via InstaCorr.\n"
       "                   ++ No other tests are made [yet] for non-stationary behavior\n"
       "                      in the time series data.\n"
     ) ;
     PRINT_AFNI_OMP_USAGE(
       "3dBandpass" ,
       "* At present, the only part of 3dBandpass that is parallelized is the\n"
       "  '-blur' option, which processes each sub-brick independently.\n"
     ) ;
     PRINT_COMPILE_DATE ; exit(0) ;
   }

   /*-- startup --*/

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

   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],"-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 ;
     }
   }

   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 ) 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 */

   mrv = THD_dset_to_vectim( inset , mask , 0 ) ;
   if( mrv == NULL ) ERROR_exit("Can't load time series data!?") ;
   DSET_unload(inset) ;

   /* 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 ;
     }
   }

   /* check whether processing leaves any DoF remaining  18 Mar 2015 [rickr] */
   {
      int nbprem = THD_bandpass_remain_dim(ntime, dt, fbot, ftop, 1);
      int bpused, nremain;
      int wlimit;               /* warning limit */

      bpused = ntime - nbprem;  /* #dim lost in bandpass step */

      nremain = nbprem - nort;  /* #dim left in output */
      if( nortset == 1 ) nremain--;
      nremain -= (qdet+1);

      if( verb ) INFO_message("%d dimensional data reduced to %d by:\n"
                    "    %d (bandpass), %d (-ort), %d (-dsort), %d (detrend)",
                    ntime, nremain, bpused, nort, nortset?1:0, qdet+1);

      /* possibly warn (if 95% lost) user or fail */
      wlimit = ntime/20;
      if( wlimit < 3 ) wlimit = 3;
      if( nremain < wlimit && nremain > 0 )
         WARNING_message("dimensionality reduced from %d to %d, be careful!",
                         ntime, nremain);
      if( nremain <= 0 ) /* FAILURE */
         ERROR_exit("dimensionality reduced from %d to %d, failing!",
                    ntime, nremain);
   }

   /* 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") ;
   (void)THD_bandpass_vectim( mrv , dt,fbot,ftop , 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 ) ;
       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( verb ) INFO_message("Creating output dataset in memory, then writing it") ;
   outset = EDIT_empty_copy(inset) ;
   /* do not copy scalars    11 Sep 2015 [rickr] */
   EDIT_dset_items( outset , ADN_prefix,prefix ,
                             ADN_brick_fac,NULL ,
                    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) ;
   DSET_write(outset) ; if( verb ) WROTE_DSET(outset) ;

   exit(0) ;
}
Exemplo n.º 6
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) ;
}
Exemplo n.º 7
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 */
}
Exemplo n.º 8
0
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *inset=NULL ;
   byte *mask=NULL ; int mask_nx=0,mask_ny=0,mask_nz=0 , automask=0 , masknum=0 ;
   int iarg=1 , verb=1 , ntype=0 , nev,kk,ii,nxyz,nt ;
   float na,nb,nc , dx,dy,dz ;
   MRI_IMARR *imar=NULL ; int *ivox ; MRI_IMAGE *pim ;
   int do_vmean=0 , do_vnorm=0 , sval_itop=0 ;
   int polort=-1 ; float *ev ;
   MRI_IMARR *ortar ; MRI_IMAGE *ortim ; int nyort=0 ;
   float bpass_L=0.0f , bpass_H=0.0f , dtime ; int do_bpass=0 ;

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
     printf(
       "Usage:  3dmaskSVD [options] inputdataset\n"
       "Author: Zhark the Gloriously Singular\n"
       "\n"
       "* Computes the principal singular vector of the time series\n"
       "    vectors extracted from the input dataset over the input mask.\n"
       "  ++ You can use the '-sval' option to change which singular\n"
       "     vectors are output.\n"
       "* The sign of the output vector is chosen so that the average\n"
       "    of arctanh(correlation coefficient) over all input data\n"
       "    vectors (from the mask) is positive.\n"
       "* The output vector is normalized: the sum of its components\n"
       "    squared is 1.\n"
       "* You probably want to use 3dDetrend (or something similar) first,\n"
       "    to get rid of annoying artifacts, such as motion, breathing,\n"
       "    dark matter interactions with the brain, etc.\n"
       "  ++ If you are lazy scum like Zhark, you might be able to get\n"
       "     away with using the '-polort' option.\n"
       "  ++ In particular, if your data time series has a nonzero mean,\n"
       "     then you probably want at least '-polort 0' to remove the\n"
       "     mean, otherwise you'll pretty much just get a constant\n"
       "     time series as the principal singular vector!\n"
       "* An alternative to this program would be 3dmaskdump followed\n"
       "    by 1dsvd, which could give you all the singular vectors you\n"
       "    could ever want, and much more -- enough to confuse you for days.\n"
       "  ++ In particular, although you COULD input a 1D file into\n"
       "     3dmaskSVD, the 1dsvd program would make much more sense.\n"
       "* This program will be pretty slow if there are over about 2000\n"
       "    voxels in the mask.  It could be made more efficient for\n"
       "    such cases, but you'll have to give Zhark some 'incentive'.\n"
       "* Result vector goes to stdout.  Redirect per your pleasures and needs.\n"
       "* Also see program 3dLocalSVD if you want to compute the principal\n"
       "    singular time series vector from a neighborhood of EACH voxel.\n"
       "  ++ (Which is a pretty slow operation!)\n"
       "* http://en.wikipedia.org/wiki/Singular_value_decomposition\n"
       "\n"
       "-------\n"
       "Options:\n"
       "-------\n"
       " -vnorm      = L2 normalize all time series before SVD [recommended!]\n"
       " -sval a     = output singular vectors 0 .. a [default a=0 = first one only]\n"
       " -mask mset  = define the mask [default is entire dataset == slow!]\n"
       " -automask   = you'll have to guess what this option does\n"
       " -polort p   = if you are lazy and didn't run 3dDetrend (like Zhark)\n"
       " -bpass L H  = bandpass [mutually exclusive with -polort]\n"
       " -ort xx.1D  = time series to remove from the data before SVD-ization\n"
       "               ++ You can give more than 1 '-ort' option\n"
       "               ++ 'xx.1D' can contain more than 1 column\n"
       " -input ddd  = alternative way to give the input dataset name\n"
       "\n"
       "-------\n"
       "Example:\n"
       "-------\n"
       " You have a mask dataset with discrete values 1, 2, ... 77 indicating\n"
       " some ROIs; you want to get the SVD from each ROI's time series separately,\n"
       " and then put these into 1 big 77 column .1D file.  You can do this using\n"
       " a csh shell script like the one below:\n"
       "\n"
       " # Compute the individual SVD vectors\n"
       " foreach mm ( `count 1 77` )\n"
       "   3dmaskSVD -vnorm -mask mymask+orig\"<${mm}..${mm}>\" epi+orig > qvec${mm}.1D\n"
       " end\n"
       " # Glue them together into 1 big file, then delete the individual files\n"
       " 1dcat qvec*.1D > allvec.1D\n"
       " /bin/rm -f qvec*.1D\n"
       " # Plot the results to a JPEG file, then compute their correlation matrix\n"
       " 1dplot -one -nopush -jpg allvec.jpg allvec.1D\n"
       " 1ddot -terse allvec.1D > allvec_COR.1D\n"
       "\n"
       " [[ If you use the bash shell,  you'll have to figure out the syntax ]]\n"
       " [[ yourself. Zhark has no sympathy for you bash shell infidels, and ]]\n"
       " [[ considers you only slightly better than those lowly Emacs users. ]]\n"
       " [[ And do NOT ever even mention 'nedit' in Zhark's august presence! ]]\n"
     ) ;
     PRINT_COMPILE_DATE ; exit(0) ;
   }

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

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

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

   INIT_IMARR(ortar) ;

   mpv_sign_meth = AFNI_yesenv("AFNI_3dmaskSVD_meansign") ;

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

     if( strcasecmp(argv[iarg],"-bpass") == 0 ){
       if( iarg+2 >= argc ) ERROR_exit("need 2 args after -bpass") ;
       bpass_L = (float)strtod(argv[++iarg],NULL) ;
       bpass_H = (float)strtod(argv[++iarg],NULL) ;
       if( bpass_L < 0.0f || bpass_H <= bpass_L )
         ERROR_exit("Illegal values after -bpass: %g %g",bpass_L,bpass_H) ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-ort") == 0 ){  /* 01 Oct 2009 */
       int nx,ny ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-ort'") ;
       ortim = mri_read_1D( argv[iarg] ) ;
       if( ortim == NULL ) ERROR_exit("-ort '%s': Can't read 1D file",argv[iarg]) ;
       nx = ortim->nx ; ny = ortim->ny ;
       if( nx == 1 && ny > 1 ){
         MRI_IMAGE *tim=mri_transpose(ortim); mri_free(ortim); ortim = tim; ny = 1;
       }
       mri_add_name(argv[iarg],ortim) ; ADDTO_IMARR(ortar,ortim) ; nyort += ny ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-polort") == 0 ){
       char *qpt ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-polort'") ;
       polort = (int)strtod(argv[iarg],&qpt) ;
       if( *qpt != '\0' ) WARNING_message("Illegal non-numeric value after -polort") ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-vnorm") == 0 ){
       do_vnorm = 1 ; 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],"-sval") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-sval'") ;
       sval_itop = (int)strtod(argv[iarg],NULL) ;
       if( sval_itop < 0 ){ sval_itop = 0 ; WARNING_message("'-sval' reset to 0") ; }
       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]) ;
       masknum = 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 two mask inputs!") ;
       automask = 1 ; iarg++ ; continue ;
     }

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

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

   /*---- 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]) ;
   }
   nt = DSET_NVALS(inset) ;  /* vector lengths */
   if( nt < 9 )
     ERROR_exit("Must have at least 9 values per voxel") ;
   if( polort+1 >= nt )
     ERROR_exit("'-polort %d' too big for time series length = %d",polort,nt) ;

   DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ;
   nxyz = DSET_NVOX(inset) ;

   DSET_UNMSEC(inset) ;
   dtime = DSET_TR(inset) ;
   if( dtime <= 0.0f ) dtime = 1.0f ;
   do_bpass = (bpass_L < bpass_H) ;
   if( do_bpass ){
     kk = THD_bandpass_OK( nt , dtime , bpass_L , bpass_H , 1 ) ;
     if( kk <= 0 ) ERROR_exit("Can't continue since -bpass setup is illegal") ;
     polort = -1 ;
   }

   /*--- deal with the masking ---*/

   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?") ;
     masknum = mmm = THD_countmask( DSET_NVOX(inset) , mask ) ;
     INFO_message("Number of voxels in automask = %d",mmm) ;
     if( mmm < 9 ) ERROR_exit("Automask is too small to process") ;
   } else {
     mask = (byte *)malloc(sizeof(byte)*nxyz) ; masknum = nxyz ;
     memset( mask , 1 , sizeof(byte)*nxyz ) ;
     INFO_message("Using all %d voxels in dataset",nxyz) ;
   }

   nev = MIN(nt,masknum) ;  /* max possible number of eigenvalues */
   if( sval_itop >= nev ){
     sval_itop = nev-1 ;
     WARNING_message("'-sval' reset to '%d'",sval_itop) ;
   }
   mri_principal_vector_params( 0 , do_vnorm , sval_itop ) ;
   mri_principal_setev(nev) ;

   /*-- get data vectors --*/

   ivox = (int *)malloc(sizeof(int)*masknum) ;
   for( kk=ii=0 ; ii < nxyz ; ii++ ) if( mask[ii] ) ivox[kk++] = ii ;
   INFO_message("Extracting data vectors") ;
   imar = THD_extract_many_series( masknum, ivox, inset ) ; DSET_unload(inset) ;
   if( imar == NULL ) ERROR_exit("Can't get data vector?!") ;

   /*-- detrending --*/

   if( polort >= 0 || nyort > 0 || do_bpass ){
     float **polref=NULL ; float *tsar ;
     int nort=IMARR_COUNT(ortar) , nref=0 ;

     if( polort >= 0 ){  /* polynomials */
       nref = polort+1 ; polref = THD_build_polyref(nref,nt) ;
     }

     if( nort > 0 ){     /* other orts */
       float *oar , *par ; int nx,ny , qq,tt ;
       for( kk=0 ; kk < nort ; kk++ ){  /* loop over input -ort files */
         ortim = IMARR_SUBIM(ortar,kk) ;
         nx = ortim->nx ; ny = ortim->ny ;
         if( nx < nt )
           ERROR_exit("-ort '%s' length %d shorter than dataset length %d" ,
                      ortim->name , nx , nt ) ;
         polref = (float **)realloc(polref,(nref+ny)*sizeof(float *)) ;
         oar    = MRI_FLOAT_PTR(ortim) ;
         for( qq=0 ; qq < ny ; qq++,oar+=nx ){
           par = polref[nref+qq] = (float *)malloc(sizeof(float)*nt) ;
           for( tt=0 ; tt < nt ; tt++ ) par[tt] = oar[tt] ;
                if( polort == 0 ) THD_const_detrend (nt,par,NULL) ;
           else if( polort >  0 ) THD_linear_detrend(nt,par,NULL,NULL) ;
         }
         nref += ny ;
       }
       DESTROY_IMARR(ortar) ;
     }

     if( !do_bpass ){            /* old style ort-ification */

       MRI_IMAGE *imq , *imp ; float *qar ;
       INFO_message("Detrending data vectors") ;
#if 1
       imq = mri_new( nt , nref , MRI_float) ; qar = MRI_FLOAT_PTR(imq) ;
       for( kk=0 ; kk < nref ; kk++ )
         memcpy( qar+kk*nt , polref[kk] , sizeof(float)*nt ) ;
       imp = mri_matrix_psinv( imq , NULL , 1.e-8 ) ;
       for( kk=0 ; kk < IMARR_COUNT(imar) ; kk++ ){
         mri_matrix_detrend( IMARR_SUBIM(imar,kk) , imq , imp ) ;
       }
       mri_free(imp) ; mri_free(imq) ;
#else
       for( kk=0 ; kk < IMARR_COUNT(imar) ; kk++ ){
         tsar = MRI_FLOAT_PTR(IMARR_SUBIM(imar,kk)) ;
         THD_generic_detrend_LSQ( nt , tsar , -1 , nref , polref , NULL ) ;
       }
#endif

     } else {                   /* bandpass plus (maybe) orts */

       float **vec = (float **)malloc(sizeof(float *)*IMARR_COUNT(imar)) ;
       INFO_message("Bandpassing data vectors") ;
       for( kk=0 ; kk < IMARR_COUNT(imar) ; kk++ )
         vec[kk] = MRI_FLOAT_PTR(IMARR_SUBIM(imar,kk)) ;
       (void)THD_bandpass_vectors( nt    , IMARR_COUNT(imar) , vec     ,
                                   dtime , bpass_L           , bpass_H ,
                                   2     , nref              , polref   ) ;
       free(vec) ;
     }

     for( kk=0 ; kk < nref; kk++ ) free(polref[kk]) ;
     free(polref) ;
   } /* end of detrendization */

   /*--- the actual work ---*/

   INFO_message("Computing SVD") ;
   pim  = mri_principal_vector( imar ) ; DESTROY_IMARR(imar) ;
   if( pim == NULL ) ERROR_exit("SVD failure!?!") ;
   ev = mri_principal_getev() ;
   switch(sval_itop+1){
     case 1:
       INFO_message("First singular value: %g",ev[0]) ; break ;
     case 2:
       INFO_message("First 2 singular values: %g %g",ev[0],ev[1]) ; break ;
     case 3:
       INFO_message("First 3 singular values: %g %g %g",ev[0],ev[1],ev[2]) ; break ;
     case 4:
       INFO_message("First 4 singular values: %g %g %g %g",ev[0],ev[1],ev[2],ev[3]) ; break ;
     default:
     case 5:
       INFO_message("First 5 singular values: %g %g %g %g %g",ev[0],ev[1],ev[2],ev[3],ev[4]) ; break ;
   }
   mri_write_1D(NULL,pim) ;

   exit(0) ;
}
Exemplo n.º 9
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) ;
}
Exemplo n.º 10
0
Arquivo: 3dTfilter.c Projeto: nno/afni
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *old_dset=NULL , *new_dset=NULL ;
   char *prefix = "Filtered" ;
   int hh=0 ;
   int nvals , nopt ;

   if( argc < 2 || strcasecmp(argv[1],"-help") == 0 ){
     printf(
      "\n"
      "3dTfilter takes as input a dataset, filters the time series in\n"
      "each voxel as ordered by the user, and outputs a new dataset.\n"
      "The data in each voxel is processed separately.\n"
      "\n"
      "The user (you?) specifies the filter functions to apply.\n"
      "They are applied in the order given on the command line:\n"
      "  -filter rank -filter adaptive:7\n"
      "means to do the following operations\n"
      "  (1) turn the data into ranks\n"
      "  (2) apply the adaptive mean filter to the ranks\n"
      "\n"
      "Notes:\n"
      "------\n"
      "** This program is a work in progress, and more capabilities\n"
      "   will be added as time allows, as the need arises, and as\n"
      "   the author's whims bubble to the surface of his febrile brain.\n"
      "\n"
      "** This program is for people who have Sisu.\n"
      "\n"
      "Options:\n"
      "--------\n"
      "\n"
      " -input inputdataset\n"
      "\n"
      " -prefix outputdataset\n"
      "\n"
      " -filter FunctionName\n"
      "     At least one '-filter' option is required!\n"
      "     The FunctionName values that you can give are:\n"
      "\n"
      "        rank       = smallest value is replaced by 0,\n"
      "                     next smallest value by 1, and so forth.\n"
      "                     ** This filter is pretty useless.\n"
      "\n"
      "        adaptive:H = adaptive mean filter with half-width of\n"
      "                     'H' time points (H > 0).\n"
      "                     ** At most one 'adaptive' filter can be used!\n"
      "                     ** The filter 'footprint' is 2*H+1 points.\n"
      "                     ** This filter does local smoothing over the\n"
      "                        'footprint', with values far away from\n"
      "                        the local median being weighted less.\n"
      "\n"
      "        detrend:P  = (least squares) detrend with polynomials of up\n"
      "                     order 'P' for P=0, 1, 2, ....\n"
      "                     ** At most one 'detrend' filter can be used!\n"
      "\n"
      "        despike    = apply the 'NEW25' despiking algorithm, as in\n"
      "                     program 3dDespike.\n"
      "\n"
      "Example:\n"
      "--------\n"
      " 3dTfilter -input fred.nii -prefix fred.af.nii -filter adaptive:7\n"
      "\n"
      "-------\n"
      "Author: The Programmer with No Name\n"
      "-------\n"
      "\n"
     ) ;
     exit(0) ;
   }

   /* bureaucracy */

   mainENTRY("3dTfilter main"); machdep(); AFNI_logger("3dTfilter",argc,argv);
   PRINT_VERSION("3dTfilter"); AUTHOR("Thorby Baslim");


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

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

      /*-- prefix --*/

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

     if( strcasecmp(argv[nopt],"-input") == 0 ||
         strcasecmp(argv[nopt],"-inset") == 0   ){
       if( ++nopt >= argc ) ERROR_exit("%s needs an argument!",argv[nopt-1]);
       if( old_dset != NULL ) ERROR_exit("you can't have 2 input datasets!") ;
       old_dset = THD_open_dataset(argv[nopt]) ;
       CHECK_OPEN_ERROR(old_dset,argv[nopt]) ;
       nopt++ ; continue ;
     }

     if( strcasecmp(argv[nopt],"-filter") == 0 ){
       if( ++nopt >= argc ) ERROR_exit("%s needs an argument!",argv[nopt-1]);

       if( strcasecmp(argv[nopt],"rank") == 0 ){
         ADD_FILTER(rank_order_float) ;
         INFO_message("Filter #%d = rank",nffunc) ;

       } else if( strncasecmp(argv[nopt],"adaptive:",9) == 0 ){
         char *cpt=argv[nopt]+9 ;
         if( hh > 0 )
           ERROR_exit("You can't use more than one 'adaptive' filter :(") ;
         if( !isdigit(*cpt) )
           ERROR_exit("'%s' is not a valid 'adaptive' filter name",argv[nopt]) ;
         hh = (int)strtod(cpt,NULL) ;
         if( hh > 29 )
           WARNING_message("Very long filter '%s' will be very slow",argv[nopt]) ;
         else if( hh <= 0 )
           ERROR_exit("'%s' is not a legal 'adaptive' filter name",argv[nopt]) ;
         ADD_FILTER(adaptive_filter) ;
         INFO_message("Filter #%d = adaptive:%d",nffunc,hh) ;

       } else if( strncasecmp(argv[nopt],"detrend:",8) == 0 ){
         char *cpt=argv[nopt]+8 ;
         if( polort > 0 )
           ERROR_exit("You can't use more than one 'detrend' filter :(") ;
         if( !isdigit(*cpt) )
           ERROR_exit("'%s' is not a valid 'detrend' filter name",argv[nopt]) ;
         polort = (int)strtod(cpt,NULL) ;
         if( polort < 0 )
           ERROR_exit("'%s' is not a legal 'detrend' filter name",argv[nopt]) ;
         ADD_FILTER(polort_filter) ;
         INFO_message("Filter #%d = detrend:%d",nffunc,polort) ;

       } else if( strcasecmp(argv[nopt],"despike") == 0 ){
         ADD_FILTER(DES_despike25) ;
         INFO_message("Filter #%d = despike",nffunc) ;

       } else {
         ERROR_exit("Unkown filter type '%s'",argv[nopt]) ;
       }
       nopt++ ; continue ;
     }

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

   if( nffunc == 0 ) ERROR_exit("No -filter options given !? :(") ;

   if( old_dset == NULL ){
     if( nopt >= argc ) ERROR_exit("no input dataset?") ;
     old_dset = THD_open_dataset(argv[nopt]) ;
     CHECK_OPEN_ERROR(old_dset,argv[nopt]) ;
   }

   nvals = DSET_NVALS(old_dset) ;
   if( nvals < 2 ) ERROR_exit("Input dataset too short to filter!") ;

   if( hh > 0 ) setup_adaptive_filter( hh , nvals ) ;

   INFO_message("Load input dataset") ;

   DSET_load(old_dset) ; CHECK_LOAD_ERROR(old_dset) ;

   /** do the work **/

   INFO_message("Start processing") ;

   new_dset = MAKER_4D_to_typed_fbuc(
                    old_dset ,             /* input dataset */
                    prefix ,               /* output prefix */
                    MRI_float ,            /* output datum  */
                    0 ,                    /* ignore count  */
                    0 ,                    /* don't detrend */
                    nvals ,                /* number of briks */
                    FILTER_tsfunc ,        /* timeseries processor */
                    NULL,                  /* data for tsfunc */
                    NULL,                  /* mask */
                    0                      /* Allow auto scaling of output */
                 ) ;

   DSET_unload(old_dset) ;

   if( new_dset != NULL ){
     tross_Copy_History( old_dset , new_dset ) ;
     tross_Make_History( "3dTfilter" , argc,argv , new_dset ) ;
     if( DSET_NUM_TIMES(old_dset) > 1 )
       EDIT_dset_items( new_dset ,
                         ADN_ntt    , DSET_NVALS(old_dset) ,
                         ADN_ttorg  , DSET_TIMEORIGIN(old_dset) ,
                         ADN_ttdel  , DSET_TR(old_dset) ,
                         ADN_tunits , UNITS_SEC_TYPE ,
                       NULL ) ;
     DSET_write( new_dset ) ; WROTE_DSET( new_dset ) ;
   } else {
     ERROR_exit("Unable to compute output dataset!\n") ;
   }

   exit(0) ;
}
Exemplo n.º 11
0
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *dset=NULL , *oset=NULL ;
   MRI_IMAGE *thim=NULL ; float *thar ; int nthar ;
   byte *mask=NULL ; int nmask=0 ;
   MRI_IMAGE *datim=NULL, *thrim=NULL , *outim=NULL ;
   int iarg , dind=0 , tind=1 , ith , nnlev=1 ;
   int scode ; float *spar=NULL ;
   char *prefix = "ETC.nii" ;

   /*-- some pitiful help --*/

   if( argc < 2 || strcasecmp(argv[1],"-help") == 0 ){
     printf("\n"
      "Usage: 3dETC [options] inputdataset\n"
      "\n"
      "Options:\n"
      "========\n"
      " -input dset  = alternative way to input the dataset\n"
      " -prefix ppp  = output prefix\n"
      " -thresh ttt  = 1D file with\n"
      "                 column #1 = p-value\n"
      "                 column #2 = cluster threshold\n"
      " -mask   mmm  = dataset with mask\n"
      " -1dindex ii  = output comes from sub-brick #ii\n"
      " -1tindex jj  = threshold on sub-brick #jj\n"
      " -NN      nn  = nn is 1 or 2 or 3 [default 1]\n"
      "\n"
      "-- Experimental - RWCox - 24 Dec 2015\n"
     ) ;
     exit(0) ;
   }

   /*-- scan options --*/

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

     if( strcasecmp(argv[iarg],"-input") == 0 ){
       if( dset != NULL )
         ERROR_exit("You can't use option '%s' twice!",argv[iarg]) ;
       if( ++iarg >= argc )
         ERROR_exit("Option '%s' needs an argument to follow!",argv[iarg-1]) ;
       dset = THD_open_dataset( argv[iarg] ) ;
       CHECK_OPEN_ERROR(dset,argv[iarg]) ;
       DSET_load(dset) ; CHECK_LOAD_ERROR(dset) ;
       iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-mask") == 0 ){
       bytevec *bvec ; int nmask_hits ;
       if( mask != NULL )
         ERROR_exit("Can't use '-mask' twice!") ;
       if( ++iarg >= argc )
         ERROR_exit("Need argument after '%s'",argv[iarg-1]) ;
       bvec = THD_create_mask_from_string(argv[iarg]) ;
       if( bvec == NULL )
         ERROR_exit("Can't create mask from '-mask' option") ;
       mask = bvec->ar ; nmask = bvec->nar ;
       nmask_hits = THD_countmask( nmask , mask ) ;
       if( nmask_hits > 0 )
         INFO_message("%d voxels in -mask definition (out of %d total)",
                      nmask_hits,nmask) ;
       else
         ERROR_exit("no nonzero voxels in -mask dataset") ;
       iarg++ ; continue ;
     }


     if( strcasecmp(argv[iarg],"-prefix") == 0 ){
       if( ++iarg >= argc )
         ERROR_exit("Option '%s' needs an argument to follow!",argv[iarg-1]) ;
       prefix = strdup(argv[iarg]) ;
       if( ! THD_filename_ok(prefix) )
         ERROR_exit("-prefix '%s' is not a good filename prefix",prefix) ;
       iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-1tindex") == 0 ){
       if( ++iarg >= argc )
         ERROR_exit("Option '%s' needs an argument to follow!",argv[iarg-1]) ;
       tind = (int)strtod(argv[iarg],NULL) ;
       if( tind < 0 )
         ERROR_exit("-tind '%s' is illegal!",argv[iarg]) ;
       iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-1dindex") == 0 ){
       if( ++iarg >= argc )
         ERROR_exit("Option '%s' needs an argument to follow!",argv[iarg-1]) ;
       dind = (int)strtod(argv[iarg],NULL) ;
       if( dind < 0 )
         ERROR_exit("-dind '%s' is illegal!",argv[iarg]) ;
       iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-NN") == 0 ){
       if( ++iarg >= argc )
         ERROR_exit("Option '%s' needs an argument to follow!",argv[iarg-1]) ;
       nnlev = (int)strtod(argv[iarg],NULL) ;
       if( nnlev < 1 || nnlev > 3 )
         ERROR_exit("-nnlev '%s' is illegal!",argv[iarg]) ;
       iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-NN1") == 0 ){
       nnlev = 1 ; iarg++ ; continue ;
     }
     if( strcasecmp(argv[iarg],"-NN2") == 0 ){
       nnlev = 2 ; iarg++ ; continue ;
     }
     if( strcasecmp(argv[iarg],"-NN3") == 0 ){
       nnlev = 3 ; iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-thresh") == 0 ){
       int nbad=0 ;
       if( thim != NULL )
         ERROR_exit("You can't use option '%s' twice!",argv[iarg]) ;
       if( ++iarg >= argc ) ERROR_exit("Option '%s' needs an argument to follow!",argv[iarg-1]) ;
       thim = mri_read_1D( argv[iarg] ) ;
       if( thim == NULL )
         ERROR_exit("Cannot read file from option -thresh '%s'",argv[iarg]) ;
       if( thim->ny < 2 )
         ERROR_exit("-thresh '%s' doesn't have at least 2 columns!",argv[iarg]) ;
       nthar = thim->nx ; thar  = MRI_FLOAT_PTR(thim) ;
       for( ith=0 ; ith < nthar ; ith++ ){
         if( thar[ith] <= 0.0f || thar[ith] > 0.10f ) nbad++ ;
       }
       if( nbad > 0 )
         ERROR_exit("Some value%s in -thresh '%s' Column #1 %s outside 0 < p <= 0.1 :-(",
                    (nbad==1)?"\0":"s" , argv[iarg] ,
                    (nbad==1)?"is":"are" ) ;
       for( ith=0 ; ith < nthar ; ith++ ){
         if( thar[ith+nthar] < 1.0f ) nbad++ ;
       }
       if( nbad > 0 )
         ERROR_exit("Some value%s in -thresh '%s' Column #2 %s less than 1 :-(",
                    (nbad==1)?"\0":"s" , argv[iarg] ,
                    (nbad==1)?"is":"are" ) ;
       INFO_message("-thresh table has %d levels of thresholding",nthar) ;
       iarg++ ; continue ;
     }

     ERROR_exit("Unknown option '%s' :-(",argv[iarg] ) ; exit(1) ;
   }

   /*-- did we get the input dataset yet? --*/

   if( dset == NULL ){
     if( iarg >= argc ) ERROR_exit("no input dataset?!") ;
     dset = THD_open_dataset( argv[iarg] ) ;
     CHECK_OPEN_ERROR(dset,argv[iarg]) ;
     DSET_load(dset) ; CHECK_LOAD_ERROR(dset) ;
     iarg++ ;
   }

   /*-- check things --*/

   if( nmask > 0 && DSET_NVOX(dset) != nmask )
     ERROR_exit("mask and input datasets don't match in number of voxels") ;

   if( thim == NULL ) ERROR_exit("no -thresh option was given!?") ;

   if( dind >= DSET_NVALS(dset) )
     ERROR_exit("data index %d is beyond end of input dataset!",dind) ;
   if( tind >= DSET_NVALS(dset) )
     ERROR_exit("threshold index %d is beyond end of input dataset!",tind) ;

   /*-- record things for posterity, et cetera --*/

   mainENTRY("3dETC main"); machdep(); AFNI_logger("3dETC",argc,argv);
   PRINT_VERSION("3dETC") ; AUTHOR("Bob the Equable") ;

   /*-- get the data and threshold volumes --*/

   datim = THD_extract_float_brick( dind , dset ) ;
   thrim = THD_extract_float_brick( tind , dset ) ;
   if( datim == NULL || thrim == NULL )  /* should be impossible */
     ERROR_exit("Can't get data and/or thresh data from input dataset???") ;
   DSET_unload(dset) ;

   scode = DSET_BRICK_STATCODE(dset,tind) ;
   if( scode < 0 )
     ERROR_exit("thresh sub-brick index %d is NOT a statistical volume!?",tind) ;
   spar = DSET_BRICK_STATAUX(dset,tind) ;

#if 1
INFO_message("value range in thrim = %g .. %g",mri_min(thrim),mri_max(thrim)) ;
#endif

   outim = mri_multi_threshold_clusterize(
             datim , scode,spar,thrim , mask ,
             nthar , thar , thar+nthar , nnlev , 0 ) ;

   oset = EDIT_empty_copy(dset) ;
   EDIT_dset_items( oset ,
                      ADN_prefix    , prefix ,
                      ADN_nvals     , 1 ,
                      ADN_ntt       , 0 ,
                      ADN_brick_fac , NULL ,
                      ADN_type      , HEAD_FUNC_TYPE ,
                      ADN_func_type , FUNC_BUCK_TYPE ,
                    ADN_none ) ;
   EDIT_substitute_brick( oset , 0 , MRI_float , MRI_FLOAT_PTR(outim) ) ;
   DSET_write(oset) ; WROTE_DSET(oset) ;

   INFO_message("# nonzero voxels = %d",mri_nonzero_count(outim)) ;

   exit(0) ;
}
Exemplo n.º 12
0
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *xset=NULL , *cset ;
   int nopt=1, datum=MRI_float, nvals, ii;
   MRI_IMAGE *ysim=NULL ;
   char *prefix = "Tcorr1D", *smethod="pearson";
   char *xnam=NULL , *ynam=NULL ;
   byte *mask=NULL ; int mask_nx,mask_ny,mask_nz , nmask=0 ;
   int do_atanh = 0 ; /* 12 Jan 2018 */

   /*----*/

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

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
      printf("Usage: 3dTcorr1D [options] xset y1D\n"
             "Computes the correlation coefficient between each voxel time series\n"
             "in the input 3D+time dataset 'xset' and each column in the 1D time\n"
             "series file 'y1D', and stores the output values in a new dataset.\n"
             "\n"
             "OPTIONS:\n"
             "  -pearson  = Correlation is the normal Pearson (product moment)\n"
             "                correlation coefficient [this is the default method].\n"
             "  -spearman = Correlation is the Spearman (rank) correlation\n"
             "                coefficient.\n"
             "  -quadrant = Correlation is the quadrant correlation coefficient.\n"
             "  -ktaub    = Correlation is Kendall's tau_b coefficient.\n"
             "              ++ For 'continuous' or finely-discretized data, tau_b and\n"
             "                 rank correlation are nearly equivalent (but not equal).\n"
             "  -dot      = Doesn't actually compute a correlation coefficient; just\n"
             "                calculates the dot product between the y1D vector(s)\n"
             "                and the dataset time series.\n"
             "\n"
             "  -Fisher   = Apply the 'Fisher' (inverse hyperbolic tangent) transformation\n"
             "                to the results.\n"
             "              ++ It does not make sense to use this with '-ktaub', but if\n"
             "                 you want to do it, the program will not stop you.\n"
             "              ++ Cannot be used with '-dot'!\n"
             "\n"
             "  -prefix p = Save output into dataset with prefix 'p'\n"
             "               [default prefix is 'Tcorr1D'].\n"
             "\n"
             "  -mask mmm = Only process voxels from 'xset' that are nonzero\n"
             "                in the 3D mask dataset 'mmm'.\n"
             "              ++ Other voxels in the output will be set to zero.\n"
             "\n"
             "  -float    = Save results in float format [the default format].\n"
             "  -short    = Save results in scaled short format [to save disk space].\n"
             "              ++ Cannot be used with '-dot'!\n"
             "\n"
             "NOTES:\n"
             "* The output dataset is functional bucket type, with one sub-brick\n"
             "   per column of the input y1D file.\n"
             "* No detrending, blurring, or other pre-processing options are available;\n"
             "   if you want these things, see 3dDetrend or 3dTproject or 3dcalc.\n"
             "   [In other words, this program presumes you know what you are doing!]\n"
             "* Also see 3dTcorrelate to do voxel-by-voxel correlation of TWO\n"
             "   3D+time datasets' time series, with similar options.\n"
             "* You can extract the time series from a single voxel with given\n"
             "   spatial indexes using 3dmaskave, and then run it with 3dTcorr1D:\n"
             "    3dmaskave -quiet -ibox 40 30 20 epi_r1+orig > r1_40_30_20.1D\n"
             "    3dTcorr1D -pearson -Fisher -prefix c_40_30_20 epi_r1+orig r1_40_30_20.1D\n"
             "* http://en.wikipedia.org/wiki/Correlation\n"
             "* http://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient\n"
             "* http://en.wikipedia.org/wiki/Spearman%%27s_rank_correlation_coefficient\n"
             "* http://en.wikipedia.org/wiki/Kendall_tau_rank_correlation_coefficient\n"
             "\n"
             "-- RWCox - Apr 2010\n"
             "         - Jun 2010: Multiple y1D columns; OpenMP; -short; -mask.\n"
            ) ;
      PRINT_AFNI_OMP_USAGE("3dTcorr1D",NULL) ;
      PRINT_COMPILE_DATE ; exit(0) ;
   }

   mainENTRY("3dTcorr1D main"); machdep(); AFNI_logger("3dTcorr1D",argc,argv);
   PRINT_VERSION("3dTcorr1D") ; THD_check_AFNI_version("3dTcorr1D") ;

   /*-- option processing --*/

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

     if( strcmp(argv[nopt],"-mask") == 0 ){  /* 28 Jun 2010 */
       THD_3dim_dataset *mset ;
       if( ++nopt >= argc ) ERROR_exit("Need argument after '-mask'") ;
       if( mask != NULL )   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 ) ;
       INFO_message("Number of voxels in mask = %d",nmask) ;
       if( nmask < 2 ) ERROR_exit("Mask is too small to process") ;
       nopt++ ; continue ;
     }

      if( strcasecmp(argv[nopt],"-float") == 0 ){  /* 27 Jun 2010 */
        datum = MRI_float ; nopt++ ; continue ;
      }
      if( strcasecmp(argv[nopt],"-short") == 0 ){
        datum = MRI_short ; nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-pearson") == 0 ){
        smethod = "pearson" ; nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-dot") == 0 ){
        smethod = "dot" ; nopt++ ; continue ;
      }


      if( strcasecmp(argv[nopt],"-spearman") == 0 || strcasecmp(argv[nopt],"-rank") == 0 ){
        smethod = "spearman" ; nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-quadrant") == 0 ){
        smethod = "quadrant" ; nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-ktaub") == 0 || strcasecmp(argv[nopt],"-taub") == 0 ){
        smethod = "ktaub" ; nopt++ ; continue ;
      }

      if( strcasecmp(argv[nopt],"-fisher") == 0 ){ /* 12 Jan 2018 */
        do_atanh = 1 ; nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-prefix") == 0 ){
        prefix = argv[++nopt] ;
        if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal value after -prefix!") ;
        nopt++ ; continue ;
      }

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

   /*------------ open datasets, check for legality ------------*/

   if( nopt+1 >= argc )
     ERROR_exit("Need 2 non-option arguments on command line!?") ;

   /* despite what the help says, if the 1D file is first, that's OK */

   if( STRING_HAS_SUFFIX(argv[nopt],"1D") ){
     ININFO_message("reading 1D file %s",argv[nopt]) ;
     ysim = mri_read_1D( argv[nopt] ) ; ynam = argv[nopt] ;
     if( ysim == NULL ) ERROR_exit("Can't read 1D file %s",argv[nopt]) ;
   } else {
     ININFO_message("reading dataset file %s",argv[nopt]) ;
     xset = THD_open_dataset( argv[nopt] ) ; xnam = argv[nopt] ;
     if( xset == NULL ) ERROR_exit("Can't open dataset %s",argv[nopt]) ;
   }

   /* read whatever type of file (3D or 1D) we don't already have */

   nopt++ ;
   if( xset != NULL ){
     ININFO_message("reading 1D file %s",argv[nopt]) ;
     ysim = mri_read_1D( argv[nopt] ) ; ynam = argv[nopt] ;
     if( ysim == NULL ) ERROR_exit("Can't read 1D file %s",argv[nopt]) ;
   } else {
     ININFO_message("reading dataset file %s",argv[nopt]) ;
     xset = THD_open_dataset( argv[nopt] ) ; xnam = argv[nopt] ;
     if( xset == NULL ) ERROR_exit("Can't open dataset %s",argv[nopt]) ;
   }

   nvals = DSET_NVALS(xset) ;  /* number of time points */
   ii    = (strcmp(smethod,"dot")==0) ? 2 : 3 ;
   if( nvals < ii )
     ERROR_exit("Input dataset %s length is less than ii?!",xnam,ii) ;

   if( ysim->nx < nvals )
     ERROR_exit("1D file %s has %d time points, but dataset has %d values",
                ynam,ysim->nx,nvals) ;
   else if( ysim->nx > nvals )
     WARNING_message("1D file %s has %d time points, dataset has %d",
                     ynam,ysim->nx,nvals) ;

   if( mri_allzero(ysim) )
     ERROR_exit("1D file %s is all zero!",ynam) ;

   if( ysim->ny > 1 )
     INFO_message("1D file %s has %d columns: correlating with ALL of them!",
                   ynam,ysim->ny) ;

   if( strcmp(smethod,"dot") == 0 && do_atanh ){
     WARNING_message("'-dot' turns off '-Fisher'") ; do_atanh = 0 ;
   }
   if( strcmp(smethod,"dot") == 0 && datum == MRI_short ){
     WARNING_message("'-dot' turns off '-short'") ; datum = MRI_float ;
   }

   cset = THD_Tcorr1D( xset, mask, nmask, ysim, smethod,
                       prefix, (datum==MRI_short) , do_atanh );
   tross_Make_History( "3dTcorr1D" , argc,argv , cset ) ;

   DSET_unload(xset) ;  /* no longer needful */

   /* finito */

   DSET_write(cset) ;
   INFO_message("Wrote dataset: %s\n",DSET_BRIKNAME(cset)) ;
   exit(0) ;
}
Exemplo n.º 13
0
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *inset=NULL , *jnset=NULL , *outset , *wset=NULL;
   int ncode=0 , code[MAX_NCODE] , iarg=1 , ii ;
   MCW_cluster *nbhd=NULL ;
   byte *mask=NULL ; int mask_nx=0,mask_ny=0,mask_nz=0 , automask=0 ;
   char *prefix="./localstat" ;
   int ntype=0 ; float na=0.0f,nb=0.0f,nc=0.0f ;
   double hist_pow=0.3333333 ; int hist_nbin=0 ;
   float hbot1=1.0f , htop1=-1.0f ; int hbot1_perc=0, htop1_perc=0 ;
   float hbot2=1.0f , htop2=-1.0f ; int hbot2_perc=0, htop2_perc=0 ;

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

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
     printf(
      "Usage: 3dLocalBistat [options] dataset1 dataset2\n"
      "\n"
      "This program computes statistics between 2 datasets,\n"
      "at each voxel, based on a local neighborhood of that voxel.\n"
      " - The neighborhood is defined by the '-nbhd' option.\n"
      " - Statistics to be calculated are defined by the '-stat' option(s).\n"
      " - The 2 input datasets should have the same number of sub-bricks.\n"
      " - OR dataset1 should have 1 sub-brick and dataset2 can have more than 1:\n"
      "   - In which case, the statistics of dataset2 against dataset1 are\n"
      "     calculated for the #0 sub-brick of dataset1 against each sub-brick\n"
      "     of dataset2.\n"
      "\n"
      "OPTIONS\n"
      "-------\n"
      " -nbhd 'nnn' = The string 'nnn' defines the region around each\n"
      "               voxel that will be extracted for the statistics\n"
      "               calculation.  The format of the 'nnn' string are:\n"
      "               * 'SPHERE(r)' where 'r' is the radius in mm;\n"
      "                 the neighborhood is all voxels whose center-to-\n"
      "                 center distance is less than or equal to 'r'.\n"
      "                 ** A negative value for 'r' means that the region\n"
      "                    is calculated using voxel indexes rather than\n"
      "                    voxel dimensions; that is, the neighborhood\n"
      "                    region is a \"sphere\" in voxel indexes of\n"
      "                    \"radius\" abs(r).\n"
      "               * 'RECT(a,b,c)' is a rectangular block which\n"
      "                 proceeds plus-or-minus 'a' mm in the x-direction,\n"
      "                 'b' mm in the y-direction, and 'c' mm in the\n"
      "                 z-direction.  The correspondence between the\n"
      "                 dataset xyz axes and the actual spatial orientation\n"
      "                 can be determined by using program 3dinfo.\n"
      "                 ** A negative value for 'a' means that the region\n"
      "                    extends plus-and-minus abs(a) voxels in the\n"
      "                    x-direction, rather than plus-and-minus a mm.\n"
      "                    Mutatis mutandum for negative 'b' and/or 'c'.\n"
      "               * 'RHDD(r)' is a rhombic dodecahedron of 'radius' r.\n"
      "               * 'TOHD(r)' is a truncated octahedron of 'radius' r.\n"
      "\n"
      " -stat sss   = Compute the statistic named 'sss' on the values\n"
      "               extracted from the region around each voxel:\n"
      "               * pearson  = Pearson correlation coefficient\n"
      "               * spearman = Spearman correlation coefficient\n"
      "               * quadrant = Quadrant correlation coefficient\n"
      "               * mutinfo  = Mutual Information\n"
      "               * normuti  = Normalized Mutual Information\n"
      "               * jointent = Joint entropy\n"
      "               * hellinger= Hellinger metric\n"
      "               * crU      = Correlation ratio (Unsymmetric)\n"
      "               * crM      = Correlation ratio (symmetrized by Multiplication)\n"
      "               * crA      = Correlation ratio (symmetrized by Addition)\n"
      "               * L2slope  = slope of least-squares (L2) linear regression of\n"
      "                            the data from dataset1 vs. the dataset2\n"
      "                            (i.e., d2 = a + b*d1 ==> this is 'b')\n"
      "               * L1slope  = slope of least-absolute-sum (L1) linear regression\n"
      "                            of the data from dataset1 vs. the dataset2\n"
      "               * num      = number of the values in the region:\n"
      "                            with the use of -mask or -automask,\n"
      "                            the size of the region around any given\n"
      "                            voxel will vary; this option lets you\n"
      "                            map that size.\n"
#if 0
      "               * ncd      = Normalized Compression Distance (zlib; very slow)\n"
#endif
#if 0 /* activate after testing */
      "               * euclidian = Euclidian distance.\n"
      "               * cityblock = City Block distance.\n"
#endif
      "               * ALL      = all of the above, in that order\n"
      "               More than one '-stat' option can be used.\n"
      "\n"
      " -mask mset  = Read in dataset 'mset' and use the nonzero voxels\n"
      "               therein as a mask.  Voxels NOT in the mask will\n"
      "               not be used in the neighborhood of any voxel. Also,\n"
      "               a voxel NOT in the mask will have its statistic(s)\n"
      "               computed as zero (0).\n"
      " -automask   = Compute the mask as in program 3dAutomask.\n"
      "               -mask and -automask are mutually exclusive: that is,\n"
      "               you can only specify one mask.\n"
      " -weight ws  = Use dataset 'ws' as a weight.  Only applies to 'pearson'.\n"
      "\n"
      " -prefix ppp = Use string 'ppp' as the prefix for the output dataset.\n"
      "               The output dataset is always stored as floats.\n"
      "\n"
      "ADVANCED OPTIONS\n"
      "----------------\n"
      " -histpow pp   = By default, the number of bins in the histogram used\n"
      "                 for calculating the Hellinger, Mutual Information,\n"
      "                 and Correlation Ratio statistics is n^(1/3), where n\n"
      "                 is the number of data points in the -nbhd mask.  You\n"
      "                 can change that exponent to 'pp' with this option.\n"
      " -histbin nn   = Or you can just set the number of bins directly to 'nn'.\n"
      " -hclip1 a b   = Clip dataset1 to lie between values 'a' and 'b'.  If 'a'\n"
      "                 and 'b' end in '%%', then these values are percentage\n"
      "                 points on the cumulative histogram.\n"
      " -hclip2 a b   = Similar to '-hclip1' for dataset2.\n"
      "\n"
      "-----------------------------\n"
      "Author: RWCox - October 2006.\n"
     ) ;
     PRINT_COMPILE_DATE ; exit(0) ;
   }

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

   PRINT_VERSION("3dLocalBistat"); mainENTRY("3dLocalBistat main"); machdep();
   AFNI_logger("3dLocalBistat",argc,argv) ;

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

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

     if( strcmp(argv[iarg],"-hclip1") == 0 ){
       char *cpt1, *cpt2 ;
       if( ++iarg >= argc-1 ) ERROR_exit("need 2 arguments after -hclip1") ;
       hbot1 = (float)strtod(argv[iarg],&cpt1) ; iarg++ ;
       htop1 = (float)strtod(argv[iarg],&cpt2) ;
       if( hbot1 >= htop1 ) ERROR_exit("illegal values after -hclip1") ;
       if( *cpt1 == '%' ){
         hbot1_perc = 1 ; hbot1 = (int)rint((double)hbot1) ;
         if( hbot1 < 0 || hbot1 > 99 ) ERROR_exit("illegal bot percentage after -hclip1") ;
       }
       if( *cpt2 == '%' ){
         htop1_perc = 1 ; htop1 = (int)rint((double)htop1) ;
         if( htop1 < 1 || htop1 > 100 ) ERROR_exit("illegal top percentage after -hclip1") ;
       }
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-hclip2") == 0 ){
       char *cpt1, *cpt2 ;
       if( ++iarg >= argc-1 ) ERROR_exit("need 2 arguments after -hclip2") ;
       hbot2 = (float)strtod(argv[iarg],&cpt1) ; iarg++ ;
       htop2 = (float)strtod(argv[iarg],&cpt2) ;
       if( hbot2 >= htop2 ) ERROR_exit("illegal values after -hclip2") ;
       if( *cpt1 == '%' ){
         hbot2_perc = 1 ; hbot2 = (int)rint((double)hbot2) ;
         if( hbot2 < 0 || hbot2 > 99 ) ERROR_exit("illegal bot percentage after -hclip2") ;
       }
       if( *cpt2 == '%' ){
         htop2_perc = 1 ; htop2 = (int)rint((double)htop2) ;
         if( htop2 < 1 || htop2 > 100 ) ERROR_exit("illegal top percentage after -hclip2") ;
       }
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-histpow") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("no argument after '%s'!",argv[iarg-1]) ;
       hist_pow = strtod(argv[iarg],NULL) ;
       if( hist_pow <= 0.0 || hist_pow > 0.5 ){
         WARNING_message("Illegal value after -histpow"); hist_pow = 0.33333;
       }
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-histbin") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("no argument after '%s'!",argv[iarg-1]) ;
       hist_nbin = (int)strtod(argv[iarg],NULL) ;
       if( hist_nbin <= 1 ) WARNING_message("Illegal value after -histbin");
       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 name after '-prefix'") ;
       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],"-weight") == 0 ){  /* 14 Aug 2007 */
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-weight'") ;
       if( wset != NULL ) ERROR_exit("Can't have two weight inputs") ;
       wset = THD_open_dataset( argv[iarg] ) ;
       CHECK_OPEN_ERROR(wset,argv[iarg]) ;
       DSET_load(wset) ; CHECK_LOAD_ERROR(wset) ;
       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],"-stat") == 0 ){
       char *cpt ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-stat'") ;
       cpt = argv[iarg] ; if( *cpt == '-' ) cpt++ ;
            if( strcasecmp(cpt,"pearson")  == 0 ) code[ncode++] = NBISTAT_PEARSON_CORR ;
       else if( strcasecmp(cpt,"spearman") == 0 ) code[ncode++] = NBISTAT_SPEARMAN_CORR;
       else if( strcasecmp(cpt,"quadrant") == 0 ) code[ncode++] = NBISTAT_QUADRANT_CORR;
       else if( strcasecmp(cpt,"mutinfo")  == 0 ) code[ncode++] = NBISTAT_MUTUAL_INFO  ;
       else if( strcasecmp(cpt,"normuti")  == 0 ) code[ncode++] = NBISTAT_NORMUT_INFO  ;
       else if( strcasecmp(cpt,"jointent") == 0 ) code[ncode++] = NBISTAT_JOINT_ENTROPY;
       else if( strcasecmp(cpt,"hellinger")== 0 ) code[ncode++] = NBISTAT_HELLINGER    ;
       else if( strcasecmp(cpt,"crU")      == 0 ) code[ncode++] = NBISTAT_CORR_RATIO_U ;
       else if( strcasecmp(cpt,"crM")      == 0 ) code[ncode++] = NBISTAT_CORR_RATIO_M ;
       else if( strcasecmp(cpt,"crA")      == 0 ) code[ncode++] = NBISTAT_CORR_RATIO_A ;
       else if( strcasecmp(cpt,"L2slope")  == 0 ) code[ncode++] = NBISTAT_L2SLOPE      ;
       else if( strcasecmp(cpt,"L1slope")  == 0 ) code[ncode++] = NBISTAT_L1SLOPE      ;
       else if( strcasecmp(cpt,"num")      == 0 ) code[ncode++] = NBISTAT_NUM          ;
#if 0
       else if( strcasecmp(cpt,"ncd")      == 0 ) code[ncode++] = NBISTAT_NCD          ;
#endif
#if 0 /* activate after testing */
       else if( strcasecmp(cpt,"euclidian")  == 0 )
                              code[ncode++] = NBISTAT_EUCLIDIAN_DIST      ;
       else if( strcasecmp(cpt,"cityblock")  == 0 )
                              code[ncode++] = NBISTAT_CITYBLOCK_DIST      ;
#endif
       else if( strcasecmp(cpt,"ALL")      == 0 ){
          code[ncode++] = NBISTAT_PEARSON_CORR ; code[ncode++] = NBISTAT_SPEARMAN_CORR;
          code[ncode++] = NBISTAT_QUADRANT_CORR; code[ncode++] = NBISTAT_MUTUAL_INFO  ;
          code[ncode++] = NBISTAT_NORMUT_INFO  ; code[ncode++] = NBISTAT_JOINT_ENTROPY;
          code[ncode++] = NBISTAT_HELLINGER    ; code[ncode++] = NBISTAT_CORR_RATIO_U ;
          code[ncode++] = NBISTAT_CORR_RATIO_M ; code[ncode++] = NBISTAT_CORR_RATIO_A ;
          code[ncode++] = NBISTAT_L2SLOPE      ; code[ncode++] = NBISTAT_L1SLOPE      ;
          code[ncode++] = NBISTAT_NUM          ;
#if 0
          code[ncode++] = NBISTAT_NCD          ;
#endif
#if 0 /* activate after testing */
         code[ncode++] = NBISTAT_EUCLIDIAN_DIST;
         code[ncode++] = NBISTAT_CITYBLOCK_DIST;
#endif
       }
       else
         ERROR_exit("-stat '%s' is an unknown statistic type",argv[iarg]) ;

       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,"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 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 {
           ERROR_exit("Unknown -nbhd shape: '%s'",cpt) ;
       }
       iarg++ ; continue ;
     }

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

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

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

   if( ncode <= 0 ) ERROR_exit("No '-stat' options given?") ;
   if( ntype <= 0 ) ERROR_exit("No '-nbhd' option given?!") ;

   /*---- deal with input datasets ----*/

   if( iarg > argc-1 ) ERROR_exit("No first input dataset on command line?") ;
   inset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(inset,argv[iarg]) ;
   iarg++ ;
   if( iarg > argc-1 ) ERROR_exit("No second input dataset on command line?") ;
   jnset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(jnset,argv[iarg]) ;
   if( jnset == NULL  ) ERROR_exit("Can't open dataset '%s'",argv[iarg]) ;
   if( DSET_NVOX(jnset)  != DSET_NVOX(inset) )
     ERROR_exit("Input datasets have different numbers of voxels!?");

   if( DSET_NVALS(jnset) != DSET_NVALS(inset)  ){
     if( DSET_NVALS(inset) > 1 ){
       ERROR_exit("Input datasets have different numbers of sub-bricks!?");
     } else {
       INFO_message("first input dataset has 1 sub-brick, second has %d",DSET_NVALS(jnset)) ;
     }
   }

   DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ;
   DSET_load(jnset) ; CHECK_LOAD_ERROR(jnset) ;

   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 , nvox ; byte *jask ;
     mask = THD_automask( inset ) ;
     if( mask == NULL )
       ERROR_message("Can't create -automask from input dataset #1?") ;
     jask = THD_automask( jnset ) ;
     if( jask == NULL )
       ERROR_message("Can't create -automask from input dataset #2?") ;
     nvox = DSET_NVOX(inset) ;
     for( ii=0 ; ii < nvox ; ii++ ) mask[ii] = (mask[ii] || jask[ii]) ;
     free(jask) ;
     mmm = THD_countmask( nvox , mask ) ;
     INFO_message("Number of voxels in dual automask = %d",mmm) ;
     if( mmm < 11 ) ERROR_exit("Automask is too small to process") ;
   }

   if( wset != NULL ){ /* 14 Aug 2007 */
     MRI_IMAGE *wim ; float *war ;
     if( DSET_NVOX(wset) != DSET_NVOX(inset) )
       ERROR_exit("-weight dataset mismatch with input datasets!") ;
     wim = mri_scale_to_float( DSET_BRICK_FACTOR(wset,0), DSET_BRICK(wset,0) );
     war = MRI_FLOAT_PTR(wim) ;
     DSET_delete(wset) ;
     if( mask != NULL ){
       int nvox = DSET_NVOX(inset) ;
       for( ii=0 ; ii < nvox ; ii++ ) if( !mask[ii] ) war[ii] = 0.0f ;
     }
     mri_bistat_setweight( wim ) ; mri_free(wim) ;
   }

   /*---- create neighborhood -----*/

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

     case NTYPE_SPHERE:{
       float dx , dy , dz ;
       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_RHDD:{
       float dx , dy , dz ;
       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 ;

     case NTYPE_TOHD:{
       float dx , dy , dz ;
       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_tohdmask( 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(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 ;
   }

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

   if( hist_nbin <= 1 ) hist_nbin = (int)pow((double)nbhd->num_pt,hist_pow) ;
   if( hist_nbin <= 1 ) hist_nbin = 2 ;
   INFO_message("2D histogram size = %d",hist_nbin) ;
   set_2Dhist_hbin( hist_nbin ) ;

   if( hbot1_perc || htop1_perc ){
     MRI_IMAGE *fim ; float perc[101] ;
     fim = THD_median_brick(inset) ;
     mri_percents(fim,100,perc) ; mri_free(fim) ;
     if( hbot1_perc ) hbot1 = perc[(int)hbot1] ;
     if( htop1_perc ) htop1 = perc[(int)htop1] ;
     INFO_message("Clipping dataset '%s' between %g and %g" ,
                  DSET_BRIKNAME(inset),hbot1,htop1 ) ;
   }
   if( hbot2_perc || htop2_perc ){
     MRI_IMAGE *fim ; float perc[101] ;
     fim = THD_median_brick(jnset) ;
     mri_percents(fim,100,perc) ; mri_free(fim) ;
     if( hbot2_perc ) hbot2 = perc[(int)hbot2] ;
     if( htop2_perc ) htop2 = perc[(int)htop2] ;
     INFO_message("Clipping dataset '%s' between %g and %g" ,
                  DSET_BRIKNAME(jnset),hbot2,htop2 ) ;
   }
   mri_nbistat_setclip( hbot1,htop1 , hbot2,htop2 ) ;

   /*---- actually do some work for a change ----*/

   THD_localbistat_verb(1) ;
   outset = THD_localbistat( inset,jnset , mask , nbhd , ncode , code ) ;

   DSET_unload(inset) ; DSET_unload(jnset) ;

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

   EDIT_dset_items( outset , ADN_prefix,prefix , ADN_none ) ;

   tross_Copy_History( inset , outset ) ;
   tross_Make_History( "3dLocalBistat" , argc,argv , outset ) ;

#if 1
   { char *lcode[66] , lll[66] ;
     lcode[0] = "Rank cor" ;
     lcode[1] = "Quad cor" ;
     lcode[2] = "Pear cor" ;
     lcode[3] = "MI" ;
     lcode[4] = "NMI" ;
     lcode[5] = "Jnt Entropy" ;
     lcode[6] = "Hlngr metric" ;
     lcode[7] = "CorRat Sym*" ;
     lcode[8] = "CorRat Sym+" ;
     lcode[9] = "CorRatUnsym" ;
     lcode[10]= "Number" ;
     lcode[11]= "NCD" ;
     lcode[12]= "Euclidian Dist";
     lcode[13]= "CityBlock Dist";
     if( DSET_NVALS(inset) == 1 ){
       for( ii=0 ; ii < DSET_NVALS(outset) ; ii++ )
         EDIT_dset_items( outset ,
                            ADN_brick_label_one+ii, lcode[code[ii%ncode]-NBISTAT_BASE],
                          ADN_none ) ;
     } else {
       for( ii=0 ; ii < DSET_NVALS(outset) ; ii++ ){
         sprintf(lll,"%s[%d]",lcode[code[ii%ncode]-NBISTAT_BASE],(ii/ncode)) ;
         EDIT_dset_items( outset , ADN_brick_label_one+ii,lll, ADN_none ) ;
       }
     }
   }
#endif

   DSET_write( outset ) ;
   WROTE_DSET( outset ) ;
   exit(0) ;
}
Exemplo n.º 14
0
Arquivo: 3dPVmap.c Projeto: afni/afni
int main( int argc , char *argv[] )
{
   char *prefix = "PVmap" , *uvpref=NULL , *cpt ;
   THD_3dim_dataset *inset=NULL , *outset=NULL , *mset=NULL ;
   char *maskname=NULL ; byte *mask=NULL ; int nmask ;
   int nopt ;
   MRI_IMAGE *pvim ;
   MRI_IMAGE *uvim ; float_pair uvlam ; float ulam , vlam , scon ;

   if( argc < 2 || ! strncmp(argv[1],"-h",2) ){
     printf("\n"
            "3dPVmap [-prefix XXX] [-mask MMM] [-automask] inputdataset\n"
            "\n"
            "Computes the first 2 principal component vectors of a\n"
            "time series datasets, then outputs the R-squared coefficient\n"
            "of each voxel time series with these first 2 components.\n"
            "\n"
            "Each voxel times series from the input dataset is minimally pre-processed\n"
            "before the PCA is computed:\n"
            "  Despiking\n"
            "  Legendre polynomial detrending\n"
            "  L2 normalizing (sum-of-squares = 1)\n"
            "If you want more impressive pre-processing, you'll have to do that\n"
            "before running 3dPVmap (e.g., use the errts dataset from afni_proc.py).\n"
            "\n"
            "Program also outputs the first 2 principal component time series\n"
            "vectors into a 1D file, for fun and profit.\n"
            "\n"
            "The fractions of total-sum-of-squares allocable to the first 2\n"
            "principal components are written to stdout at the end of the program.\n"
            "along with a 3rd number that is a measure of the spatial concentration\n"
            "or dispersion of the PVmap.\n"
            "\n"
            "These values can be captured into a file by Unix shell redirection\n"
            "or into a shell variable by assigment:\n"
            "  3dPVmap -mask AUTO Fred.nii > Fred.sval.1D\n"
            "  set sval = ( `3dPVmap -mask AUTO Fred.nii` )  # csh syntax\n"
            "If the first value is very large, for example, this might indicate\n"
            "the widespread presence of some artifact in the dataset.\n"
            "\n"
            "If the 3rd number is bigger than 1, it indicates that the PVmap\n"
            "is more concentrated in space; if it is less than one, it indicates\n"
            "that it is more dispersed in space (relative to a uniform density).\n"
            "  3dPVmap -mask AUTO Zork.nii\n"
            "  ++ mask has 21300 voxels\n"
            "  ++ Output dataset ./PVmap+orig.BRIK\n"
            "  0.095960 0.074847 1.356635\n"
            "The first principal component accounted for 9.6%% of the total sum-of-squares,\n"
            "the second component for 7.5%%, and the PVmap is fairly concentrated in space.\n"
            "These %% values are not very unusual, but the concentration is fairly high\n"
            "and the dataset should be further investigated.\n"
            "\n"
            "A concentration value below 1 indicates the PVmap is fairly dispersed; this\n"
            "often means the larger PVmap values are found near the edges of the brain\n"
            "and can be caused by motion or respiration artifacts.\n"
            "\n"
            "The goal is to visualize any widespread time series artifacts.\n"
            "For example, if a 'significant' part of the brain shows R-squared > 0.25,\n"
            "that could be a subject for concern -- look at your data!\n"
            "\n"
            "Author: Zhark the Unprincipaled\n\n"
           ) ;
     exit(0) ;
   }

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

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

     if( strcmp(argv[nopt],"-mask") == 0 ){
       if( ++nopt >= argc ) ERROR_exit("-mask needs an argument!");
       maskname = strdup(argv[nopt]) ;
       nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-automask") == 0 ){  /* 18 Apr 2019 */
       maskname = strdup("AUTO") ;
       nopt++ ; continue ;
     }

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

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

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

   inset = THD_open_dataset(argv[nopt]) ;
   CHECK_OPEN_ERROR(inset,argv[nopt]) ;
   if( DSET_NVALS(inset) < 9 ) ERROR_exit("input dataset too short") ;

   if( maskname != NULL ){
     if( strncasecmp(maskname,"AUTO",4) != 0 ){
       mset = THD_open_dataset(maskname) ;
       CHECK_OPEN_ERROR(mset,maskname) ;
       if( !EQUIV_GRIDXYZ(inset,mset) )
         ERROR_exit("-mask and input dataset don't match") ;
       mask = THD_makemask( mset , 0 , 1.0f,0.0f ) ;
       nmask = THD_countmask( DSET_NVOX(mset) , mask ) ;
     } else {
       mask = THD_automask(inset) ;
       if( mask == NULL ) ERROR_exit("Can't make automask :(") ;
       nmask = THD_countmask( DSET_NVOX(inset) , mask ) ;
     }
     INFO_message("mask has %d voxels",nmask) ;
     if( nmask < 9 ) ERROR_exit("mask is too small") ;
   } else {
     nmask = DSET_NVOX(inset) ;
     INFO_message("No mask == using all %d voxels",nmask) ;
   }

   pvim = THD_dataset_to_pvmap( inset , mask ) ;

   if( pvim == NULL ) ERROR_exit("Can't compute PVmap :(") ;
   DSET_unload(inset) ;

   outset = EDIT_empty_copy(inset) ;
   EDIT_dset_items( outset ,
                         ADN_prefix     , prefix   ,
                         ADN_datum_all  , MRI_float ,
                         ADN_nvals      , 1        ,
                         ADN_ntt        , 0        ,
                         ADN_type       , HEAD_FUNC_TYPE ,
                         ADN_func_type  , FUNC_FIM_TYPE ,
                    ADN_none ) ;
   EDIT_substitute_brick( outset , 0 , MRI_float , MRI_FLOAT_PTR(pvim) ) ;

   tross_Copy_History( inset , outset ) ;
   tross_Make_History( "3dPVmap", argc,argv, outset ) ;
   DSET_write(outset) ;
   WROTE_DSET(outset) ;

   uvim = mri_pvmap_get_vecpair() ;
   uvlam = mri_pvmap_get_lampair() ;

   uvpref = (char *)malloc(sizeof(char)*(strlen(prefix)+32)) ;
   strcpy(uvpref,prefix) ;
   cpt = strstr(uvpref,".nii" ) ; if( cpt != NULL ) *cpt = '\0' ;
   cpt = strstr(uvpref,".HEAD") ; if( cpt != NULL ) *cpt = '\0' ;
   cpt = strrchr(uvpref,'+'   ) ; if( cpt != NULL ) *cpt = '\0' ;
   strcat(uvpref,".1D") ;
   mri_write_1D( uvpref , uvim ) ;

   ulam = uvlam.a*uvlam.a / nmask ;
   vlam = uvlam.b*uvlam.b / nmask ;
   scon = mri_spatial_concentration(pvim) ;
   printf("%.6f %.6f %.6f\n",ulam,vlam,scon) ;

   exit(0) ;
}
Exemplo n.º 15
0
int main( int argc , char *argv[] )
{
   int iarg , ct , do_GM=0 ;
   int do_T2=0 ; float T2_uperc=98.5f ; byte *T2_mask=NULL ;
   char *prefix = "Unifized" ;
   THD_3dim_dataset *inset=NULL , *outset=NULL ;
   MRI_IMAGE *imin , *imout ;
   float clfrac=0.2f ;

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

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
     printf("\n"
            "Usage: 3dUnifize [options] inputdataset\n\n"
            "* The input dataset is supposed to be a T1-weighted volume,\n"
            "  possibly already skull-stripped (e.g., via 3dSkullStrip).\n"
            "  ++ However, this program can be a useful step to take BEFORE\n"
            "     3dSkullStrip, since the latter program can fail if the input\n"
            "     volume is strongly shaded -- 3dUnifize will (mostly) remove\n"
            "     such shading artifacts.\n"
            "* The output dataset has the white matter (WM) intensity approximately\n"
            "  uniformized across space, and scaled to peak at about 1000.\n"
            "* The output dataset is always stored in float format!\n"
            "* If the input dataset has more than 1 sub-brick, only sub-brick\n"
            "  #0 will be processed!\n"
            "* Method: Obi-Wan's personal variant of Ziad's sneaky trick.\n"
            "  (If you want to know what his trick is, you'll have to ask him, or\n"
            "   read Obi-Wan's source code, which is a world of ecstasy and exaltation,\n"
            "   or just read all the way to the end of this help output.)\n"
            "* The principal motive for this program is for use in an image\n"
            "  registration script, and it may or may not be useful otherwise.\n"
            "\n"
            "--------\n"
            "Options:\n"
            "--------\n"
            "  -prefix pp = Use 'pp' for prefix of output dataset.\n"
            "  -input dd  = Alternative way to specify input dataset.\n"
            "  -T2        = Treat the input as if it were T2-weighted, rather than\n"
            "               T1-weighted. This processing is done simply by inverting\n"
            "               the image contrast, processing it as if that result were\n"
            "               T1-weighted, and then re-inverting the results.\n"
            "              ++ This option is NOT guaranteed to be useful for anything!\n"
            "              ++ Of course, nothing in AFNI comes with a guarantee :-)\n"
            "              ++ If you want to be REALLY sneaky, giving this option twice\n"
            "                 will skip the second inversion step, so the result will\n"
            "                 look like a T1-weighted volume (except at the edges and\n"
            "                 near blood vessels).\n"
            "              ++ Might be useful for skull-stripping T2-weighted datasets.\n"
            "              ++ Don't try the '-T2 -T2' trick on FLAIR-T2-weighted datasets.\n"
            "                 The results aren't pretty!\n"
            "  -GM        = Also scale to unifize 'gray matter' = lower intensity voxels\n"
            "               (to aid in registering images from different scanners).\n"
            "              ++ This option is recommended for use with 3dQwarp when\n"
            "                 aligning 2 T1-weighted volumes, in order to make the\n"
            "                 WM-GM contrast about the same for the datasets, even\n"
            "                 if they don't come from the same scanner/pulse-sequence.\n"
            "              ++ Note that standardizing the contrasts with 3dUnifize will help\n"
            "                 3dQwarp match the source dataset to the base dataset.  If you\n"
            "                 later want the original source dataset to be warped, you can\n"
            "                 do so using the 3dNwarpApply program.\n"
            "  -Urad rr   = Sets the radius (in voxels) of the ball used for the sneaky trick.\n"
            "               ++ Default value is %.1f, and should be changed proportionally\n"
            "                  if the dataset voxel size differs significantly from 1 mm.\n"
            "  -ssave ss  = Save the scale factor used at each voxel into a dataset 'ss'.\n"
            "               ++ This is the white matter scale factor, and does not include\n"
            "                  the factor from the '-GM' option (if that was included).\n"
            "               ++ The input dataset is multiplied by the '-ssave' image\n"
            "                  (voxel-wise) to get the WM-unifized image.\n"
            "               ++ Another volume (with the same grid dimensions) could be\n"
            "                  scaled the same way using 3dcalc, if that is needed.\n"
            "  -quiet     = Don't print the fun fun fun progress messages (but whyyyy?).\n"
            "               ++ For the curious, the codes used are:\n"
            "                   A = Automask\n"
            "                   D = Duplo down (process a half-size volume)\n"
            "                   V = Voxel-wise histograms to get local scale factors\n"
            "                   U = duplo Up (convert local scale factors to full-size volume)\n"
            "                   W = multiply by White matter factors\n"
            "                   G = multiply by Gray matter factors [cf the -GM option]\n"
            "                   I = contrast inversion              [cf the -T2 option]\n"
            "               ++ 'Duplo down' means to scale the input volume to be half the\n"
            "                  grid size in each direction for speed when computing the\n"
            "                  voxel-wise histograms.  The sub-sampling is done using the\n"
            "                  median of the central voxel value and its 6 nearest neighbors.\n"
            "\n"
            "------------------------------------------\n"
            "Special options for Jedi AFNI Masters ONLY:\n"
            "------------------------------------------\n"
            "  -rbt R b t = Specify the 3 parameters for the algorithm, as 3 numbers\n"
            "               following the '-rbt':\n"
            "                 R = radius; same as given by option '-Urad'     [default=%.1f]\n"
            "                 b = bottom percentile of normalizing data range [default=%.1f]\n"
            "                 r = top percentile of normalizing data range    [default=%.1f]\n"
            "\n"
            "  -T2up uu   = Set the upper percentile point used for T2-T1 inversion.\n"
            "               The default value is 98.5 (for no good reason), and 'uu' is\n"
            "               allowed to be anything between 90 and 100 (inclusive).\n"
            "               ++ The histogram of the data is built, and the uu-th percentile\n"
            "                  point value is called 'U'. The contrast inversion is simply\n"
            "                  given by output_value = max( 0 , U - input_value ).\n"
            "\n"
            "  -clfrac cc = Set the automask 'clip level fraction' to 'cc', which\n"
            "               must be a number between 0.1 and 0.9.\n"
            "               A small 'cc' means to make the initial threshold\n"
            "               for clipping (a la 3dClipLevel) smaller, which\n"
            "               will tend to make the mask larger.  [default=0.1]\n"
            "               ++ [22 May 2013] The previous version of this program used a\n"
            "                  clip level fraction of 0.5, which proved to be too large\n"
            "                  for some users, who had images with very strong shading issues.\n"
            "                  Thus, the default value for this parameter was lowered to 0.1.\n"
            "               ++ [24 May 2016] The default value for this parameter was\n"
            "                  raised to 0.2, since the lower value often left a lot of\n"
            "                  noise outside the head on non-3dSkullStrip-ed datasets.\n"
            "                  You can still manually set -clfrac to 0.1 if you need to\n"
            "                  correct for very large shading artifacts.\n"
            "               ++ If the results of 3dUnifize have a lot of noise outside the head,\n"
            "                  then using '-clfrac 0.5' value will probably help.\n"
#ifndef USE_ALL_VALS
            "\n"
            "  -useall    = The 'old' way of operating was to use all dataset values\n"
            "               in the local WM histogram.  The 'new' way [May 2016] is to\n"
            "               only use positive values.  If you want to use the 'old' way,\n"
            "               then this option is what you want.\n"
#endif
            "\n"
            "-- Feb 2013 - by Obi-Wan Unifobi\n"
#ifdef USE_OMP
            "-- This code uses OpenMP to speed up the slowest part (voxel-wise histograms).\n"
#endif
            , Uprad , Uprad , Upbot , Uptop ) ;

     printf("\n"
      "----------------------------------------------------------------------------\n"
      "HOW IT WORKS (Ziad's sneaky trick is revealed at last! And more.)\n"
      "----------------------------------------------------------------------------\n"
      "The basic idea is that white matter in T1-weighted images is reasonably\n"
      "uniform in intensity, at least when averaged over 'large-ish' regions.\n"
      "\n"
      "The first step is to create a local white matter intensity volume.\n"
      "Around each voxel (inside the volume 'automask'), the ball of values\n"
      "within a fixed radius (default=18.3 voxels) is extracted and these\n"
      "numbers are sorted.  The values in the high-intensity range of the\n"
      "histogram (default=70%% to 80%%) are averaged.  The result from this\n"
      "step is a smooth 3D map of the 'white matter intensity' (WMI).\n"
      "\n"
      " [The parameters of the above process can be altered with the '-rbt' option.]\n"
      " [For speed, the WMI map is produced on an image that is half-size in all   ]\n"
      " [directions ('Duplo down'), and then is expanded back to the full-size     ]\n"
      " [volume ('Duplo up').  The automask procedure can be somewhat controlled   ]\n"
      " [via the '-clfrac' option.  The default setting is designed to deal with   ]\n"
      " [heavily shaded images, where the WMI varies by a factor of 5 or more over ]\n"
      " [the image volume.                                                         ]\n"
      "\n"
      "The second step is to scale the value at every voxel location x in the input\n"
      "volume by the factor 1000/WMI(x), so that the 'white matter intensity' is\n"
      "now uniform-ized to be 1000 everywhere.  (This is Ziad's 'trick'; it is easy,\n"
      "works well, and doesn't require fitting some spatial model to the data: the\n"
      "data provides its own model.)\n"
      "\n"
      "If the '-GM' option is used, then this scaled volume is further processed\n"
      "to make the lower intensity values (presumably gray matter) have a contrast\n"
      "similar to that from a collection of 3 Tesla MP-RAGE images that were\n"
      "acquired at the NIH.  (This procedure is not Ziad's fault, and should be\n"
      "blamed on the reclusive Obi-Wan Unifobi.)\n"
      "\n"
      "From the WM-uniform-ized volume, the median of all values larger than 1000\n"
      "is computed; call this value P.  P-1000 represents the upward dispersion\n"
      "of the high-intensity (white matter) voxels in the volume.  This value is\n"
      "'reflected' below 1000 to Q = 1000 - 2*(P-1000), and Q is taken to be the\n"
      "upper bound for gray matter voxel intensities.  A lower bound for gray\n"
      "matter voxel values is estimated via the 'clip fraction' algorithm as\n"
      "implemented in program 3dClipLevel; call this lower bound R.  The median\n"
      "of all values between R and Q is computed; call this value G, which is taken\n"
      "to be a 'typical' gray matter voxel instensity.  Then the values z in the\n"
      "entire volume are linearly scaled by the formula\n"
      "   z_out = (1000-666)/(1000-G) * (z_in-1000) + 1000\n"
      "so that the WM uniform-ized intensity of 1000 remains at 1000, and the gray\n"
      "matter median intensity of G is mapped to 666.  (Values z_out that end up\n"
      "negative are set to 0; as a result, some of CSF might end up as 0.)\n"
      "The value 666 was chosen because it gave results visually comparable to\n"
      "various NIH-generated 3 Tesla T1-weighted datasets.  (Any suggestions that\n"
      "this value was chosen for other reasons will be treated as 'beastly'.)\n"
      "\n"
      "To recap: the WM uniform-ization process provides a linear scaling factor\n"
      "that varies for each voxel ('local'), while the GM normalization process\n"
      "uses a global linear scaling.  The GM process is optional, and is simply\n"
      "designed to make the various T1-weighted images look similar.\n"
      "\n"
      "-----** CAVEAT **-----\n"
      "This procedure was primarily developed to aid in 3D registration, especially\n"
      "when using 3dQwarp, so that the registration algorithms are trying to match\n"
      "images that are alike.  It is *NOT* intended to be used for quantification\n"
      "purposes, such as Voxel Based Morphometry!  That would better be done via\n"
      "the 3dSeg program, which is far more complicated.\n"
      "----------------------------------------------------------------------------\n"
     ) ;
     PRINT_COMPILE_DATE ; exit(0) ;
   }

   mainENTRY("3dUnifize main"); machdep(); AFNI_logger("3dUnifize",argc,argv);
   PRINT_VERSION("3dUnifize") ;
   ct = NI_clock_time() ;

   /*-- scan command line --*/

   THD_automask_set_clipfrac(0.1f) ;  /* 22 May 2013 */
   THD_automask_extclip(1) ;          /* 19 Dec 2014 */

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

     if( strcmp(argv[iarg],"-clfrac") == 0 || strcmp(argv[iarg],"-mfrac") == 0 ){    /* 22 May 2013 */
       if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ;
       clfrac = (float)strtod( argv[iarg] , NULL ) ;
       if( clfrac < 0.1f || clfrac > 0.9f )
         ERROR_exit("-clfrac value %f is illegal!",clfrac) ;
       THD_automask_set_clipfrac(clfrac) ;
       iarg++ ; continue ;
     }

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

     if( strcmp(argv[iarg],"-ssave") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ;
       sspref = strdup(argv[iarg]) ;
       if( !THD_filename_ok(sspref) ) ERROR_exit("Illegal value after -ssave!") ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-input") == 0 || strcmp(argv[iarg],"-inset") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ;
       if( inset  != NULL ) ERROR_exit("Can't use '%s' twice"    ,argv[iarg-1]) ;
       inset = THD_open_dataset( argv[iarg] ) ;
       CHECK_OPEN_ERROR(inset,argv[iarg]) ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-Urad") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ;
       Uprad = (float)strtod(argv[iarg],NULL) ;
       if( Uprad <   5.0f || Uprad > 40.0f )
         ERROR_exit("Illegal value %f after option -Urad",Uprad) ;
       iarg++ ; continue ;
     }

#ifndef USE_ALL_VALS
     if( strcmp(argv[iarg],"-useall") == 0 ){   /* 17 May 2016 */
       USE_ALL_VALS = 1 ; iarg++ ; continue ;
     }
#else
     if( strcmp(argv[iarg],"-useall") == 0 ){
       WARNING_message("-useall option is disabled in this version") ;
       iarg++ ; continue ;
     }
#endif

     if( strcmp(argv[iarg],"-param") == 0 ||      /*--- HIDDEN OPTION ---*/
         strcmp(argv[iarg],"-rbt"  ) == 0    ){
       if( ++iarg >= argc-2 ) ERROR_exit("Need 3 arguments (R pb pt) after '%s'",argv[iarg-1]) ;
       Uprad = (float)strtod(argv[iarg++],NULL) ;
       Upbot = (float)strtod(argv[iarg++],NULL) ;
       Uptop = (float)strtod(argv[iarg++],NULL) ;
       if( Uprad <   5.0f || Uprad > 40.0f ||
           Upbot <  30.0f || Upbot > 80.0f ||
           Uptop <= Upbot || Uptop > 90.0f   )
         ERROR_exit("Illegal values (R pb pt) after '%s'",argv[iarg-4]) ;
       continue ;
     }

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

     if( strcasecmp(argv[iarg],"-T2") == 0 ){  /* 18 Dec 2014 */
       do_T2++ ; iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-T2up") == 0 ){  /* 18 Dec 2014 */
       T2_uperc = (float)strtod( argv[++iarg] , NULL ) ;
       if( T2_uperc < 90.0f || T2_uperc > 100.0f )
         ERROR_exit("-T2up value is out of range 90..100 :-(") ;
       iarg++ ; continue ;
     }

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

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

   /* read input dataset, if not already there */

   if( inset == NULL ){
     if( iarg >= argc ) ERROR_exit("No dataset name on command line?\n") ;
     inset = THD_open_dataset( argv[iarg] ) ;
     CHECK_OPEN_ERROR(inset,argv[iarg]) ;
   }

   if( verb ) fprintf(stderr," + Pre-processing: ") ;

   /* load input from disk */

   DSET_load( inset ) ; CHECK_LOAD_ERROR(inset) ;
   if( DSET_NVALS(inset) > 1 )
     WARNING_message("Only processing sub-brick #0 (out of %d)",DSET_NVALS(inset)) ;

   /* make a float copy for processing */

   imin = mri_to_float( DSET_BRICK(inset,0) ) ; DSET_unload(inset) ;
   if( imin == NULL ) ERROR_exit("Can't copy input dataset brick?!") ;

#if 0
THD_cliplevel_search(imin) ; exit(0) ;  /* experimentation only */
#endif

   THD_automask_set_clipfrac(clfrac) ;

   /* invert T2? */

   if( do_T2 ){
     if( verb ) fprintf(stderr,"I") ;
     T2_mask = mri_automask_image(imin) ;
     mri_invertcontrast_inplace( imin , T2_uperc , T2_mask ) ;
   }

   /* do the actual work */

   imout = mri_WMunifize(imin) ;          /* local WM scaling */
   free(imin) ;

   if( sspref != NULL && sclim != NULL ){  /* 25 Jun 2013 */
     STATUS("output -ssave") ;
     outset = EDIT_empty_copy( inset )  ;
     EDIT_dset_items( outset ,
                         ADN_prefix , sspref ,
                         ADN_nvals  , 1 ,
                         ADN_ntt    , 0 ,
                      ADN_none ) ;
     EDIT_substitute_brick( outset , 0 , MRI_float , MRI_FLOAT_PTR(sclim) ) ;
     tross_Copy_History( inset , outset ) ;
     tross_Make_History( "3dUnifize" , argc,argv , outset ) ;
     DSET_write(outset) ; outset = NULL ;
   }
   if( sclim != NULL ){ mri_free(sclim) ; sclim = NULL ; }

   if( imout == NULL ){                   /* this is bad-ositiness */
     if( verb ) fprintf(stderr,"\n") ;
     ERROR_exit("Can't compute Unifize-d dataset for some reason :-(") ;
   }

   if( do_GM ) mri_GMunifize(imout) ;     /* global GM scaling */

   if( do_T2 == 1 ){          /* re-invert T2? */
     if( verb ) fprintf(stderr,"I") ;
     mri_invertcontrast_inplace( imout , T2_uperc , T2_mask ) ;
   } else if( do_T2 == 2 ){   /* don't re-invert, but clip off bright edges */
     mri_clipedges_inplace( imout , PKVAL*1.111f , PKVAL*1.055f ) ;
   }

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

   /* create output dataset, and write it into the historical record */

   outset = EDIT_empty_copy( inset )  ;
   EDIT_dset_items( outset ,
                       ADN_prefix , prefix ,
                       ADN_nvals  , 1 ,
                       ADN_ntt    , 0 ,
                    ADN_none ) ;
   EDIT_substitute_brick( outset , 0 , MRI_float , MRI_FLOAT_PTR(imout) ) ;
   tross_Copy_History( inset , outset ) ;
   tross_Make_History( "3dUnifize" , argc,argv , outset ) ;
   DSET_write(outset) ;
   WROTE_DSET(outset) ;
   DSET_delete(outset) ; DSET_delete(inset) ;

   /* vamoose the ranch */

   if( verb ){
     double cput = COX_cpu_time() ;
     if( cput > 0.05 )
       INFO_message("===== CPU time = %.1f sec  Elapsed = %.1f\n",
                             COX_cpu_time() , 0.001*(NI_clock_time()-ct) ) ;
     else
       INFO_message("===== Elapsed = %.1f sec\n", 0.001*(NI_clock_time()-ct) ) ;
   }
   exit(0) ;
}
Exemplo n.º 16
0
int main( int argc , char *argv[] )
{
   int iarg=1 , ii,nvox , nvals ;
   THD_3dim_dataset *inset=NULL, *outset=NULL , *mset=NULL ;
   char *prefix="./blurinmask" ;
   float fwhm_goal=0.0f ; int fwhm_2D=0 ;
   byte *mask=NULL ; int mask_nx=0,mask_ny=0,mask_nz=0 , automask=0 , nmask=0 ;
   float dx,dy,dz=0.0f , *bar , val ;
   int floatize=0 ;    /* 18 May 2009 */

   MRI_IMAGE *immask=NULL ;    /* 07 Oct 2009 */
   short      *mmask=NULL ;
   short      *unval_mmask=NULL ; int nuniq_mmask=0 ;
   int do_preserve=0 , use_qsar ;         /* 19 Oct 2009 */

   THD_3dim_dataset *fwhmset=NULL ;
   MRI_IMAGE *fxim=NULL, *fyim=NULL, *fzim=NULL ; /* 13 Jun 2016 */
   int niter_fxyz=0 ; float dmax=0.0f , dmin=0.0f ;

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

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

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
     printf(
      "Usage: ~1~\n"
      "3dBlurInMask [options]\n"
      "Blurs a dataset spatially inside a mask. That's all. Experimental.\n"
      "\n"
      "OPTIONS ~1~\n"
      "-------\n"
      " -input  ddd = This required 'option' specifies the dataset\n"
      "               that will be smoothed and output.\n"
      " -FWHM   f   = Add 'f' amount of smoothness to the dataset (in mm).\n"
      "              **N.B.: This is also a required 'option'.\n"
      " -FWHMdset d = Read in dataset 'd' and add the amount of smoothness\n"
      "               given at each voxel -- spatially variable blurring.\n"
      "              ** EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL **\n"
      " -mask   mmm = Mask dataset, if desired.  Blurring will\n"
      "               occur only within the mask.  Voxels NOT in\n"
      "               the mask will be set to zero in the output.\n"
      " -Mmask  mmm = Multi-mask dataset -- each distinct nonzero\n"
      "               value in dataset 'mmm' will be treated as\n"
      "               a separate mask for blurring purposes.\n"
      "              **N.B.: 'mmm' must be byte- or short-valued!\n"
      " -automask   = Create an automask from the input dataset.\n"
      "              **N.B.: only 1 masking option can be used!\n"
      " -preserve   = Normally, voxels not in the mask will be\n"
      "               set to zero in the output.  If you want the\n"
      "               original values in the dataset to be preserved\n"
      "               in the output, use this option.\n"
      " -prefix ppp = Prefix for output dataset will be 'ppp'.\n"
      "              **N.B.: Output dataset is always in float format.\n"
      " -quiet      = Don't be verbose with the progress reports.\n"
      " -float      = Save dataset as floats, no matter what the\n"
      "               input data type is.\n"
      "              **N.B.: If the input dataset is unscaled shorts, then\n"
      "                      the default is to save the output in short\n"
      "                      format as well.  In EVERY other case, the\n"
      "                      program saves the output as floats. Thus,\n"
      "                      the ONLY purpose of the '-float' option is to\n"
      "                      force an all-shorts input dataset to be saved\n"
      "                      as all-floats after blurring.\n"
      "\n"
      "NOTES ~1~\n"
      "-----\n"
      " * If you don't provide a mask, then all voxels will be included\n"
      "     in the blurring.  (But then why are you using this program?)\n"
      " * Note that voxels inside the mask that are not contiguous with\n"
      "     any other voxels inside the mask will not be modified at all!\n"
      " * Works iteratively, similarly to 3dBlurToFWHM, but without\n"
      "     the extensive overhead of monitoring the smoothness.\n"
      " * But this program will be faster than 3dBlurToFWHM, and probably\n"
      "     slower than 3dmerge.\n"
      " * Since the blurring is done iteratively, rather than all-at-once as\n"
      "     in 3dmerge, the results will be slightly different than 3dmerge's,\n"
      "     even if no mask is used here (3dmerge, of course, doesn't take a mask).\n"
      " * If the original FWHM of the dataset was 'S' and you input a value\n"
      "     'F' with the '-FWHM' option, then the output dataset's smoothness\n"
      "     will be about sqrt(S*S+F*F).  The number of iterations will be\n"
      "     about (F*F/d*d) where d=grid spacing; this means that a large value\n"
      "     of F might take a lot of CPU time!\n"
      " * The spatial smoothness of a 3D+time dataset can be estimated with a\n"
      "     command similar to the following:\n"
      "          3dFWHMx -detrend -mask mmm+orig -input ddd+orig\n"
     ) ;
     printf(
      " * The minimum number of voxels in the mask is %d\n",MASK_MIN) ;
     printf(
      " * Isolated voxels will be removed from the mask!\n") ;

     PRINT_AFNI_OMP_USAGE("3dBlurInMask",NULL) ;
     PRINT_COMPILE_DATE ; exit(0) ;
   }

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

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

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

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

     if( strncmp(argv[iarg],"-preserve",5) == 0 ){  /* 19 Oct 2009 */
       do_preserve = 1 ; iarg++ ; continue ;
     }

     if( strncmp(argv[iarg],"-qui",4) == 0 ){
       verb = 0 ; iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-ver",4) == 0 ){
       verb++ ; iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-input") == 0 || strcmp(argv[iarg],"-dset") == 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]) ;
       if( !THD_filename_ok(prefix) ) ERROR_exit("Bad name after '-prefix'") ;
       iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-Mmask") == 0 ){   /* 07 Oct 2009 */
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-Mmask'") ;
       if( mmask != NULL || 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);
#if 0
       if( !MRI_IS_INT_TYPE(DSET_BRICK_TYPE(mset,0)) )
         ERROR_exit("-Mmask dataset is not integer type!") ;
#endif
       immask = mri_to_short( 1.0 , DSET_BRICK(mset,0) ) ;
       mmask  = MRI_SHORT_PTR(immask) ;
       unval_mmask = UniqueShort( mmask, mask_nx*mask_ny*mask_nz, &nuniq_mmask, 0 ) ;
       if( unval_mmask == NULL || nuniq_mmask == 0 )
         ERROR_exit("-Mmask dataset cannot be processed!?") ;
       if( nuniq_mmask == 1 && unval_mmask[0] == 0 )
         ERROR_exit("-Mmask dataset is all zeros!?") ;
       if( verb ){
         int qq , ww ;
         for( ii=qq=0 ; ii < nuniq_mmask ; ii++ ) if( unval_mmask[ii] != 0 ) qq++ ;
         for( ii=ww=0 ; ii < immask->nvox ; ii++ ) if( mmask[ii] != 0 ) ww++ ;
         INFO_message("%d unique nonzero values in -Mmask; %d nonzero voxels",qq,ww) ;
       }
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-mask") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask'") ;
       if( mmask != NULL || 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_unload(mset) ;
       if( mask == NULL ) ERROR_exit("Can't make mask from dataset '%s'",argv[iarg]) ;
       ii = THD_mask_remove_isolas( mask_nx,mask_ny,mask_nz , mask ) ;
       if( verb && ii > 0 ) INFO_message("Removed %d isola%s from mask dataset",ii,(ii==1)?"\0":"s") ;
       nmask = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ;
       if( verb ) INFO_message("Number of voxels in mask = %d",nmask) ;
       if( nmask < MASK_MIN ) ERROR_exit("Mask is too small to process") ;
       iarg++ ; continue ;
     }

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

     if( strcasecmp(argv[iarg],"-FWHM") == 0 || strcasecmp(argv[iarg],"-FHWM") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]);
       val = (float)strtod(argv[iarg],NULL) ;
       if( val <= 0.0f ) ERROR_exit("Illegal value after '%s': '%s'",
                                    argv[iarg-1],argv[iarg]) ;
       fwhm_goal = val ; fwhm_2D = 0 ;
       iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-FWHMdset") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]);
       if( fwhmset != NULL ) ERROR_exit("You can't use option '-FWHMdset' twice :(") ;
       fwhmset = THD_open_dataset( argv[iarg] ) ;
       CHECK_OPEN_ERROR(fwhmset,argv[iarg]) ;
       do_preserve = 1 ; iarg++ ; continue ;
     }

     if( strncmp(argv[iarg],"-float",6) == 0 ){    /* 18 May 2009 */
       floatize = 1 ; iarg++ ; continue ;
     }

#if 0
     if( strcmp(argv[iarg],"-FWHMxy") == 0 || strcmp(argv[iarg],"-FHWMxy") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]);
       val = (float)strtod(argv[iarg],NULL) ;
       if( val <= 0.0f ) ERROR_exit("Illegal value after '%s': '%s'",
                                    argv[iarg-1],argv[iarg]) ;
       fwhm_goal = val ; fwhm_2D = 1 ;
       iarg++ ; continue ;
     }
#endif

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

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

   /*----- check for stupid inputs, load datasets, et cetera -----*/

   if( fwhmset == NULL && fwhm_goal == 0.0f )
     ERROR_exit("No -FWHM option given! What do you want?") ;

   if( fwhmset != NULL && fwhm_goal > 0.0f ){
     WARNING_message("-FWHMdset option replaces -FWHM value") ;
     fwhm_goal = 0.0f ;
   }

   if( fwhmset != NULL && mmask != NULL )
     ERROR_exit("Sorry: -FWHMdset and -Mmask don't work together (yet)") ;

   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]) ;
   }

   nvox = DSET_NVOX(inset)     ;
   dx   = fabs(DSET_DX(inset)) ; if( dx == 0.0f ) dx = 1.0f ;
   dy   = fabs(DSET_DY(inset)) ; if( dy == 0.0f ) dy = 1.0f ;
   dz   = fabs(DSET_DZ(inset)) ; if( dz == 0.0f ) dz = 1.0f ;

   dmax = MAX(dx,dy) ; if( dmax < dz ) dmax = dz ;  /* 13 Jun 2016 */
   dmin = MIN(dx,dy) ; if( dmin > dz ) dmin = dz ;

   if( !floatize ){    /* 18 May 2009 */
     if( !THD_datum_constant(inset->dblk)     ||
         THD_need_brick_factor(inset)         ||
         DSET_BRICK_TYPE(inset,0) != MRI_short  ){
       if( verb ) INFO_message("forcing output to be stored in float format") ;
       floatize = 1 ;
     } else {
       if( verb ) INFO_message("output dataset will be stored as shorts") ;
     }
   } else {
       if( verb ) INFO_message("output dataset will be stored as floats") ;
   }

#if 0
   if( DSET_NZ(inset) == 1 && !fwhm_2D ){
     WARNING_message("Dataset is 2D ==> switching from -FWHM to -FWHMxy") ;
     fwhm_2D = 1 ;
   }
#endif

   /*--- deal with mask or automask ---*/

   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 ){
     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 < MASK_MIN ) ERROR_exit("Automask is too small to process") ;

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

   } else {
     mask = (byte *)malloc(sizeof(byte)*nvox) ; nmask = nvox ;
     memset(mask,1,sizeof(byte)*nvox) ;
     if( verb ) INFO_message("No mask ==> processing all %d voxels",nvox);
   }

   /*--- process FWHMdset [13 Jun 2016] ---*/

   if( fwhmset != NULL ){
     float *fxar,*fyar,*fzar , *fwar ; MRI_IMAGE *fwim ;
     float fwmax=0.0f , fsx,fsy,fsz ; int ii, nfpos=0 ;

     if( DSET_NX(inset) != DSET_NX(fwhmset) ||
         DSET_NY(inset) != DSET_NY(fwhmset) ||
         DSET_NZ(inset) != DSET_NZ(fwhmset)   )
       ERROR_exit("grid dimensions for FWHMdset and input dataset do not match :(") ;

STATUS("get fwim") ;
     DSET_load(fwhmset) ;
     fwim = mri_scale_to_float(DSET_BRICK_FACTOR(fwhmset,0),DSET_BRICK(fwhmset,0));
     fwar = MRI_FLOAT_PTR(fwim);
     DSET_unload(fwhmset) ;
STATUS("process fwar") ;
     for( ii=0 ; ii < nvox ; ii++ ){
       if( mask[ii] && fwar[ii] > 0.0f ){
         nfpos++ ;
         if( fwar[ii] > fwmax ) fwmax = fwar[ii] ;
       } else {
         fwar[ii] = 0.0f ; mask[ii] = 0 ;
       }
     }
     if( nfpos < 100 )
       ERROR_exit("Cannot proceed: too few (%d) voxels are positive in -FWHMdset!",nfpos) ;

     niter_fxyz = (int)rintf(2.0f*fwmax*fwmax*FFAC/(0.05f*dmin*dmin)) + 1 ;

     if( verb ) INFO_message("-FWHMdset: niter=%d  npos=%d",niter_fxyz,nfpos) ;

STATUS("create fxim etc.") ;

     fxim = mri_new_conforming(fwim,MRI_float); fxar = MRI_FLOAT_PTR(fxim);
     fyim = mri_new_conforming(fwim,MRI_float); fyar = MRI_FLOAT_PTR(fyim);
     fzim = mri_new_conforming(fwim,MRI_float); fzar = MRI_FLOAT_PTR(fzim);

     fsx = FFAC/(dx*dx*niter_fxyz) ;
     fsy = FFAC/(dy*dy*niter_fxyz) ;
     fsz = FFAC/(dz*dz*niter_fxyz) ;
/** INFO_message("fsx=%g fsy=%g fsz=%g",fsx,fsy,fsz) ; **/

     for( ii=0 ; ii < nvox ; ii++ ){
       if( fwar[ii] > 0.0f ){
         fxar[ii] = fwar[ii]*fwar[ii] * fsx ;
         fyar[ii] = fwar[ii]*fwar[ii] * fsy ;
         fzar[ii] = fwar[ii]*fwar[ii] * fsz ;
       } else {
         fxar[ii] = fyar[ii] = fzar[ii] = 0.0f ;
       }
     }

STATUS("free(fwim)") ;
     mri_free(fwim) ;
   }

   /*--- process input dataset ---*/

STATUS("load input") ;

   DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ;

   outset = EDIT_empty_copy( inset ) ;   /* moved here 04 Jun 2007 */
   EDIT_dset_items( outset , ADN_prefix , prefix , ADN_none ) ;
   EDIT_dset_items( outset , ADN_brick_fac , NULL , ADN_none ) ;  /* 11 Sep 2007 */
   tross_Copy_History( inset , outset ) ;
   tross_Make_History( "3dBlurInMask" , argc,argv , outset ) ;

   nvals = DSET_NVALS(inset) ;

   use_qsar = (do_preserve || mmask != NULL) ; /* 19 Oct 20090 */

 AFNI_OMP_START ;
#pragma omp parallel if( nvals > 1 )
 {
   MRI_IMAGE *dsim ; int ids,qit ; byte *qmask=NULL ; register int vv ;
   MRI_IMAGE *qim=NULL, *qsim=NULL; float *qar=NULL, *dsar, *qsar=NULL;
#pragma omp critical (MALLOC)
   { if( use_qsar ){
       qsim  = mri_new_conforming(DSET_BRICK(inset,0),MRI_float); qsar = MRI_FLOAT_PTR(qsim);
     }
     if( mmask != NULL ){
       qmask = (byte *)malloc(sizeof(byte)*nvox) ;
       qim   = mri_new_conforming(immask,MRI_float); qar  = MRI_FLOAT_PTR(qim);
       qim->dx = dx ; qim->dy = dy ; qim->dz = dz ;
     }
   }
#pragma omp for
   for( ids=0 ; ids < nvals ; ids++ ){
#pragma omp critical (MALLOC)
     { dsim = mri_scale_to_float(DSET_BRICK_FACTOR(inset,ids),DSET_BRICK(inset,ids));
       DSET_unload_one(inset,ids) ;
     }
     dsim->dx = dx ; dsim->dy = dy ; dsim->dz = dz ; dsar = MRI_FLOAT_PTR(dsim) ;

     /* if needed, initialize qsar with data to be preserved in output */

     if( do_preserve ){
       for( vv=0 ; vv < nvox ; vv++ ) qsar[vv] = dsar[vv] ;
     } else if( mmask != NULL ){
       for( vv=0 ; vv < nvox ; vv++ ) qsar[vv] = 0.0f ;
     }

     if( fwhmset != NULL ){       /* 13 Jun 2016: spatially variable blurring */

       for( qit=0 ; qit < niter_fxyz ; qit++ ){
         mri_blur3D_variable( dsim , mask , fxim,fyim,fzim ) ;
       }
       if( do_preserve ){
         for( vv=0 ; vv < nvox ; vv++ ) if( mask[vv] ) qsar[vv] = dsar[vv] ;
       }

     } else if( mmask != NULL ){         /* 07 Oct 2009: multiple masks */
       int qq ; register short uval ;
       for( qq=0 ; qq < nuniq_mmask ; qq++ ){
         uval = unval_mmask[qq] ; if( uval == 0 ) continue ;
         for( vv=0 ; vv < nvox ; vv++ ) qmask[vv] = (mmask[vv]==uval) ; /* make mask */
         (void)THD_mask_remove_isolas( mask_nx,mask_ny,mask_nz , qmask ) ;
         nmask = THD_countmask( nvox , qmask ) ;
         if( verb && ids==0 ) ININFO_message("voxels in Mmask[%d] = %d",uval,nmask) ;
         if( nmask >= MASK_MIN ){
           /* copy data from dataset to qar */
           for( vv=0 ; vv < nvox ; vv++ ) if( qmask[vv] ) qar[vv] = dsar[vv] ;
           /* blur qar (output will be zero where qmask==0) */
           mri_blur3D_addfwhm( qim , qmask , fwhm_goal ) ;  /** the real work **/
           /* copy results back to qsar */
           for( vv=0 ; vv < nvox ; vv++ ) if( qmask[vv] ) qsar[vv] = qar[vv] ;
         }
       }

     } else {                      /* the olden way: 1 mask */

       mri_blur3D_addfwhm( dsim , mask , fwhm_goal ) ;  /** all the work **/

       /* dsim will be zero where mask==0;
          if we want to preserve the input values, copy dsar into qsar now
          at all mask!=0 voxels, since qsar contains the original data values */

       if( do_preserve ){
         for( vv=0 ; vv < nvox ; vv++ ) if( mask[vv] ) qsar[vv] = dsar[vv] ;
       }

     }

     /* if necessary, copy combined results in qsar to dsar for output */

     if( use_qsar ){
       for( vv=0 ; vv < nvox ; vv++ ) dsar[vv] = qsar[vv] ;
     }

     if( floatize ){
       EDIT_substitute_brick( outset , ids , MRI_float , dsar ) ;
     } else {
#pragma omp critical (MALLOC)
       { EDIT_substscale_brick( outset , ids , MRI_float , dsar ,
                                               MRI_short , 1.0f  ) ;
         mri_free(dsim) ;
       }
     }
   } /* end of loop over sub-bricks */

#pragma omp critical (MALLOC)
   { if( qsim   != NULL ) mri_free(qsim);
     if( immask != NULL ){ free(qmask); mri_free(qim); }
   }
 } /* end OpenMP */
 AFNI_OMP_END ;

   if(   mask != NULL )     free(  mask) ;
   if( immask != NULL ) mri_free(immask) ;

   DSET_unload(inset) ;
   DSET_write(outset) ;
   WROTE_DSET(outset) ;
   exit(0) ;
}
Exemplo n.º 17
0
THD_3dim_dataset * MAKER_4D_to_typed_fim( THD_3dim_dataset * old_dset ,
                                          char * new_prefix , int new_datum ,
                                          int ignore , int detrend ,
                                          generic_func * user_func ,
                                          void * user_data )
{
   THD_3dim_dataset * new_dset ;  /* output dataset */

   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) */
   complex ** cptr = NULL ;

   float * fxar = NULL ;  /* array loaded from input dataset */
   float * fac  = NULL ;  /* array of brick scaling factors */
   float * fout = NULL ;  /* will be array of output floats */
   float * dtr  = NULL ;  /* will be array of detrending coeff */

   float val , d0fac , d1fac , x0,x1;
   double tzero=0 , tdelta , ts_mean , ts_slope ;
   int   ii , old_datum , nuse , use_fac , iz,izold, nxy,nvox , nbad ;
   register int kk ;

   void (*ufunc)(double,double,int,float *,double,double,void *,float *)
     = (void (*)(double,double,int,float *,double,double,void *,float *)) user_func ;

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

   if( ! ISVALID_3DIM_DATASET(old_dset) ) return NULL ;

   if( new_datum >= 0         &&
       new_datum != MRI_byte  &&
       new_datum != MRI_short &&
       new_datum != MRI_float   ) return NULL ;

   if( user_func == NULL ) return NULL ;

   if( ignore < 0 ) ignore = 0 ;

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

   old_datum = DSET_BRICK_TYPE( old_dset , 0 ) ;   /* get old dataset datum */
   nuse      = DSET_NUM_TIMES(old_dset) - ignore ; /* # of points on time axis */
   if( nuse < 2 ) return NULL ;

   if( new_datum < 0 ) new_datum = old_datum ;   /* output datum = input */
   if( new_datum == MRI_complex ) return NULL ;  /* but complex = bad news */

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

   kk = THD_count_databricks( old_dset->dblk ) ;  /* check if it was */
   if( kk < DSET_NVALS(old_dset) ){               /* loaded correctly */
      DSET_unload( old_dset ) ;
      return NULL ;
   }

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

      default:                      /** don't know what to do **/
         DSET_unload( old_dset ) ;
         return NULL ;

      /** create array of pointers into old dataset sub-bricks **/

      /*--------- 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 NULL ;
         for( kk=0 ; kk < nuse ; kk++ )
            bptr[kk] = (byte *) DSET_ARRAY(old_dset,kk+ignore) ;
      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 NULL ;
         for( kk=0 ; kk < nuse ; kk++ )
            sptr[kk] = (short *) DSET_ARRAY(old_dset,kk+ignore) ;
      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 NULL ;
         for( kk=0 ; kk < nuse ; kk++ )
            fptr[kk] = (float *) DSET_ARRAY(old_dset,kk+ignore) ;
      break ;

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

      case MRI_complex:
         cptr = (complex **) malloc( sizeof(complex *) * nuse ) ;
         if( cptr == NULL ) return NULL ;
         for( kk=0 ; kk < nuse ; kk++ )
            cptr[kk] = (complex *) DSET_ARRAY(old_dset,kk+ignore) ;
      break ;

   } /* end of switch on input type */

   /*---- allocate space for 1 voxel timeseries ----*/

   fxar = (float *) malloc( sizeof(float) * nuse ) ;   /* voxel timeseries */
   if( fxar == NULL ){ FREE_WORKSPACE ; return NULL ; }

   /*--- get scaling factors for sub-bricks ---*/

   fac = (float *) malloc( sizeof(float) * nuse ) ;   /* factors */
   if( fac == NULL ){ FREE_WORKSPACE ; return NULL ; }

   use_fac = 0 ;
   for( kk=0 ; kk < nuse ; kk++ ){
      fac[kk] = DSET_BRICK_FACTOR(old_dset,kk+ignore) ;
      if( fac[kk] != 0.0 ) use_fac++ ;
      else                 fac[kk] = 1.0 ;
   }
   if( !use_fac ) FREEUP(fac) ;

   /*--- setup for detrending ---*/

   dtr = (float *) malloc( sizeof(float) * nuse ) ;
   if( dtr == NULL ){ FREE_WORKSPACE ; return NULL ; }

   d0fac = 1.0 / nuse ;
   d1fac = 12.0 / nuse / (nuse*nuse - 1.0) ;
   for( kk=0 ; kk < nuse ; kk++ )
      dtr[kk] = kk - 0.5 * (nuse-1) ;  /* linear trend, orthogonal to 1 */

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

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

   /*-- 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       , 1 ,                    /* # sub-bricks */
              ADN_ntt         , 0 ,                    /* # time points */
              ADN_type        , ISHEAD(old_dset)       /* dataset type */
                                 ? HEAD_FUNC_TYPE
                                 : GEN_FUNC_TYPE ,
              ADN_func_type   , FUNC_FIM_TYPE ,        /* function type */
           ADN_none ) ;

   if( ii != 0 ){
      ERROR_message("Error creating dataset '%s'",new_prefix) ;
      THD_delete_3dim_dataset( new_dset , False ) ;  /* some error above */
      FREE_WORKSPACE ; return NULL ;
   }

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

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

   fout = (float *) malloc( sizeof(float) * nvox ) ;  /* ptr to brick */

   if( fout == NULL ){
      THD_delete_3dim_dataset( new_dset , False ) ;
      FREE_WORKSPACE ; return NULL ;
   }

   /*----- set up to find time at each voxel -----*/

   tdelta = old_dset->taxis->ttdel ;
   if( DSET_TIMEUNITS(old_dset) == UNITS_MSEC_TYPE ) tdelta *= 0.001 ;
   if( tdelta == 0.0 ) tdelta = 1.0 ;

   izold  = -666 ;
   nxy    = old_dset->daxes->nxx * old_dset->daxes->nyy ;

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

   /* start notification */

#if 0
   user_func(  0.0 , 0.0 , nvox , NULL,0.0,0.0 , user_data , NULL ) ;
#else
   ufunc(  0.0 , 0.0 , nvox , NULL,0.0,0.0 , user_data , NULL ) ;
#endif

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

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

      /*** load data from input dataset, depending on type ***/

      switch( old_datum ){

         /*** input = bytes ***/

         case MRI_byte:
            for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] = bptr[kk][ii] ;
         break ;

         /*** input = shorts ***/

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

         /*** input = floats ***/

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

         /*** input = complex (note we use absolute value) ***/

         case MRI_complex:
            for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] = CABS(cptr[kk][ii]) ;
         break ;

      } /* end of switch over input type */

      /*** scale? ***/

      if( use_fac )
         for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] *= fac[kk] ;

      /** compute mean and slope **/

      x0 = x1 = 0.0 ;
      for( kk=0 ; kk < nuse ; kk++ ){
         x0 += fxar[kk] ; x1 += fxar[kk] * dtr[kk] ;
      }

      x0 *= d0fac ; x1 *= d1fac ;  /* factors to remove mean and trend */

      ts_mean  = x0 ;
      ts_slope = x1 / tdelta ;

      /** detrend? **/

      if( detrend )
         for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] -= (x0 + x1 * dtr[kk]) ;

      /** compute start time of this timeseries **/

      iz = ii / nxy ;    /* which slice am I in? */

      if( iz != izold ){          /* in a new slice? */
         tzero = THD_timeof( ignore ,
                             old_dset->daxes->zzorg
                           + iz*old_dset->daxes->zzdel , old_dset->taxis ) ;
         izold = iz ;

         if( DSET_TIMEUNITS(old_dset) == UNITS_MSEC_TYPE ) tzero *= 0.001 ;
      }

      /*** compute output ***/

#if 0
      user_func( tzero,tdelta , nuse,fxar,ts_mean,ts_slope , user_data , fout+ii ) ;
#else
      ufunc( tzero,tdelta , nuse,fxar,ts_mean,ts_slope , user_data , fout+ii ) ;
#endif

   } /* end of outer loop over 1 voxels at a time */

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

   /* end notification */

#if 0
   user_func( 0.0 , 0.0 , 0 , NULL,0.0,0.0 , user_data , NULL ) ;
#else
   ufunc( 0.0 , 0.0 , 0 , NULL,0.0,0.0 , user_data , NULL ) ;
#endif

   nbad = thd_floatscan( nvox , fout ) ;  /* 08 Aug 2000 */
   if( nbad > 0 )
      fprintf(stderr,
              "++ Warning: %d bad floats computed in MAKER_4D_to_typed_fim\n\a",
              nbad ) ;

   /*------------------------------------------------------------*/
   /*------- The output is now in fout[ii], 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 brick to the dataset ***/

      case MRI_float:
         EDIT_substitute_brick( new_dset , 0 , MRI_float , fout ) ;
         fout = NULL ;  /* so it won't be freed later */
      break ;

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

      case MRI_short:{
         short * bout ;
         float sfac ;

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

         bout = (short *) malloc( sizeof(short) * nvox ) ;
         if( bout == NULL ){
            fprintf(stderr,
             "\nFinal malloc error in MAKER_4D_to_fim - is memory exhausted?\n\a");
            EXIT(1) ;
         }

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

         sfac = MCW_vol_amax( nvox,1,1 , MRI_float , fout ) ;
         if( sfac > 0.0 ){
            sfac = 32767.0 / sfac ;
            EDIT_coerce_scale_type( nvox,sfac ,
                                    MRI_float,fout , MRI_short,bout ) ;
            sfac = 1.0 / sfac ;
         }

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

         EDIT_substitute_brick( new_dset , 0 , MRI_short , bout ) ;
         EDIT_dset_items( new_dset , ADN_brick_fac , &sfac , ADN_none ) ;
      }
      break ;

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

      case MRI_byte:{
         byte * bout ;
         float sfac ;

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

         bout = (byte *) malloc( sizeof(byte) * nvox ) ;
         if( bout == NULL ){
            fprintf(stderr,
             "\nFinal malloc error in MAKER_4D_to_fim - is memory exhausted?\n\a");
            EXIT(1) ;
         }

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

         sfac = MCW_vol_amax( nvox,1,1 , MRI_float , fout ) ;
         if( sfac > 0.0 ){
            sfac = 255.0 / sfac ;
            EDIT_coerce_scale_type( nvox,sfac ,
                                    MRI_float,fout , MRI_byte,bout ) ;
            sfac = 1.0 / sfac ;
         }

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

         EDIT_substitute_brick( new_dset , 0 , MRI_byte , bout ) ;
         EDIT_dset_items( new_dset , ADN_brick_fac , &sfac , ADN_none ) ;
      }
      break ;

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

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

   FREE_WORKSPACE ;
   return new_dset ;
}
Exemplo n.º 18
0
void UC_read_opts( int argc , char * argv[] )
{
   int nopt = 1 ;
   float val ;
   int  kk, nxyz, mm,nn ;
   float * vv , * bb ;

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

      /**** -verbose ****/

      if( strncmp(argv[nopt],"-verbose",5) == 0 ){
         UC_be_quiet = 0 ;
         nopt++ ; continue ;
      }

      /**** -ref file.1D ****/

      if( strncmp(argv[nopt],"-ref",4) == 0 ){
         MRI_IMAGE * im ;
         nopt++ ;
         if( nopt >= argc ) UC_syntax("-ref needs an argument!") ;
         im = mri_read( argv[nopt] ) ;
         if( im == NULL ) UC_syntax("Can't read -ref file!") ;
         if( im->kind == MRI_float ){
            UC_ref = im ;
         } else {
            UC_ref = mri_to_float(im) ; mri_free(im) ;
         }
         im = mri_transpose(UC_ref) ; mri_free(UC_ref) ; UC_ref = im ;
         nopt++ ; continue ;
      }

      /**** -prefix prefix ****/

      if( strncmp(argv[nopt],"-prefix",6) == 0 ){
         nopt++ ;
         if( nopt >= argc ) UC_syntax("-prefix needs an argument!") ;
         MCW_strncpy( UC_prefix , argv[nopt++] , THD_MAX_PREFIX ) ;
         continue ;
      }

      /**** -mask mset ****/

      if( strncmp(argv[nopt],"-mask",5) == 0 ){
         THD_3dim_dataset * mset ; int ii ;
         nopt++ ;
         if( nopt >= argc ) UC_syntax("need arguments after -mask!") ;
         mset = THD_open_dataset( argv[nopt] ) ;
         if( mset == NULL ) UC_syntax("can't open -mask dataset!") ;
         UC_mask = THD_makemask( mset , 0 , 1.0,0.0 ) ;
         UC_mask_nvox = DSET_NVOX(mset) ;
         DSET_delete(mset) ;
         if( UC_mask == NULL ) UC_syntax("can't use -mask dataset!") ;
         UC_mask_hits = THD_countmask( UC_mask_nvox , UC_mask ) ;
         if( UC_mask_hits == 0 ) UC_syntax("mask is all zeros!") ;
         if( !UC_be_quiet ) printf("--- %d voxels in mask\n",UC_mask_hits) ;
         nopt++ ; continue ;
      }

      /**** unknown switch ****/

      fprintf(stderr,"\n*** unrecognized option %s\n",argv[nopt]) ;
      exit(1) ;

   }  /* end of loop over options */

   /*--- a simple consistency check ---*/

   /*--- last input is dataset name ---*/

   if( nopt >= argc ) UC_syntax("no input dataset name?") ;

   UC_dset = THD_open_dataset( argv[nopt] ) ;
   if( !ISVALID_3DIM_DATASET(UC_dset) ){
      fprintf(stderr,"\n*** can't open dataset file %s\n",argv[nopt]) ;
      exit(1) ;
   }

   nxyz = DSET_NVOX(UC_dset) ;
   if( UC_mask != NULL && nxyz != UC_mask_nvox )
      UC_syntax("mask and input dataset size mismatch!") ;

   /*--- load vectors ---*/

   UC_nvec = (UC_mask_hits > 0) ? UC_mask_hits : nxyz ;
   UC_vdim = DSET_NVALS(UC_dset) ;
   if( UC_vdim < 4 )
      UC_syntax("input dataset needs at least 4 sub-bricks!") ;

   if( UC_ref == NULL || UC_ref->nx < UC_vdim )
      UC_syntax("input ref not long enough for input dataset!") ;

   vv     = (float *) malloc( sizeof(float) * UC_nvec * UC_vdim ) ;
   UC_vec = (float **) malloc( sizeof(float *) * UC_nvec ) ;
   for( kk=0 ; kk < UC_nvec ; kk++ ) UC_vec[kk] = vv + (kk*UC_vdim) ;

   if( !UC_be_quiet ) printf("--- reading dataset\n") ;
   DSET_load(UC_dset) ;  CHECK_LOAD_ERROR(UC_dset) ;

   /* copy brick data into float storage */

   if( !UC_be_quiet ) printf("--- loading vectors\n") ;

   bb = (float *) malloc( sizeof(float) * nxyz ) ;
   for( mm=0 ; mm < UC_vdim ; mm++ ){

      EDIT_coerce_type( nxyz , DSET_BRICK_TYPE(UC_dset,mm) ,
                               DSET_ARRAY(UC_dset,mm) ,
                        MRI_float , bb ) ;

      DSET_unload_one( UC_dset , mm ) ;

      if( UC_mask == NULL ){
         for( kk=0 ; kk < nxyz ; kk++ ) UC_vec[kk][mm] = bb[kk] ;
      } else {
         for( nn=kk=0 ; kk < nxyz ; kk++ )
            if( UC_mask[kk] ) UC_vec[nn++][mm] = bb[kk] ;
      }
   }
   free(bb) ; DSET_unload( UC_dset ) ;

   /* detrend and normalize vectors */

   if( !UC_be_quiet ) printf("--- normalizing vectors\n") ;

   for( kk=0 ; kk < UC_nvec ; kk++ )
      normalize( UC_vdim , UC_vec[kk] ) ;

   for( kk=0 ; kk < UC_ref->ny ; kk++ )
      normalize( UC_vdim , MRI_FLOAT_PTR(UC_ref) + kk*UC_ref->nx ) ;

   return ;
}
Exemplo n.º 19
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) ;
}
Exemplo n.º 20
0
int main( int argc , char * argv[] )
{
   float mrad=0.0f , fwhm=0.0f ;
   int nrep=1 ;
   char *prefix = "Polyfit" ;
   char *resid  = NULL ;
   char *cfnam  = NULL ;
   int iarg , verb=0 , do_automask=0 , nord=3 , meth=2 , do_mclip=0 ;
   THD_3dim_dataset *inset ;
   MRI_IMAGE *imout , *imin ;
   byte *mask=NULL ; int nvmask=0 , nmask=0 , do_mone=0 , do_byslice=0 ;
   MRI_IMARR *exar=NULL ;
   floatvec *fvit=NULL ;   /* 26 Feb 2019 */

   if( argc < 2 || strcasecmp(argv[1],"-help") == 0 ){
      printf("\n"
             "Usage: 3dPolyfit [options] dataset   ~1~\n"
             "\n"
             "* Fits a polynomial in space to the input dataset and outputs that fitted dataset.\n"
             "\n"
             "* You can also add your own basis datasets to the fitting mix, using the\n"
             "  '-base' option.\n"
             "\n"
             "* You can get the fit coefficients using the '-1Dcoef' option.\n"
             "\n"
             "--------\n"
             "Options:   ~1~\n"
             "--------\n"
             "\n"
             "  -nord n    = Maximum polynomial order (0..9) [default order=3]\n"
             "                [n=0 is the constant 1]\n"
             "                [n=-1 means only use volumes from '-base']\n"
             "\n"
             "  -blur f    = Gaussian blur input dataset (inside mask) with FWHM='f' (mm)\n"
             "\n"
             "  -mrad r    = Radius (voxels) of preliminary median filter of input\n"
             "                [default is no blurring of either type; you can]\n"
             "                [do both types (Gaussian and median), but why??]\n"
             "                [N.B.: median blur is slower than Gaussian]\n"
             "\n"
             "  -prefix pp = Use 'pp' for prefix of output dataset (the fit).\n"
             "                [default prefix is 'Polyfit'; use NULL to skip this output]\n"
             "\n"
             "  -resid  rr = Use 'rr' for the prefix of the residual dataset.\n"
             "                [default is not to output residuals]\n"
             "\n"
             "  -1Dcoef cc = Save coefficients of fit into text file cc.1D.\n"
             "                [default is not to save these coefficients]\n"
             "\n"
             "  -automask  = Create a mask (a la 3dAutomask)\n"
             "  -mask mset = Create a mask from nonzero voxels in 'mset'.\n"
             "                [default is not to use a mask, which is probably a bad idea]\n"
             "\n"
             "  -mone      = Scale the mean value of the fit (inside the mask) to 1.\n"
             "                [probably this option is not useful for anything]\n"
             "\n"
             "  -mclip     = Clip fit values outside the rectilinear box containing the\n"
             "               mask to the edge of that box, to avoid weird artifacts.\n"
             "\n"
             "  -meth mm   = Set 'mm' to 2 for least squares fit;\n"
             "               set it to 1 for L1 fit [default method=2]\n"
             "                [Note that L1 fitting is slower than L2 fitting!]\n"
             "\n"
             "  -base bb   = In addition to the polynomial fit, also use\n"
             "               the volumes in dataset 'bb' as extra basis functions.\n"
             "                [If you use a base dataset, then you can set nord]\n"
             "                [to -1, to skip using any spatial polynomial fit.]\n"
             "\n"
             "  -verb      = Print fun and useful progress reports :-)\n"
             "\n"
             "------\n"
             "Notes:   ~1~\n"
             "------\n"
             "* Output dataset is always stored in float format.\n"
             "\n"
             "* If the input dataset has more than 1 sub-brick, only sub-brick #0\n"
             "  is processed. To fit more than one volume, you'll have to use a script\n"
             "  to loop over the input sub-bricks, and then glue (3dTcat) the results\n"
             "  together to get a final result. A simple example:\n"
             "     #!/bin/tcsh\n"
             "     set base = model.nii\n"
             "     set dset = errts.nii\n"
             "     set nval = `3dnvals $dset`\n"
             "     @ vtop = $nval - 1\n"
             "     foreach vv ( `count 0 $vtop` )\n"
             "       3dPolyfit -base \"$base\" -nord 0 -mask \"$base\" -1Dcoef QQ.$vv -prefix QQ.$vv.nii $dset\"[$vv]\"\n"
             "     end\n"
             "     3dTcat -prefix QQall.nii QQ.0*.nii\n"
             "     1dcat  QQ.0*.1D > QQall.1D\n"
             "     \rm QQ.0*\n"
             "     exit 0\n"
             "\n"
             "* If the '-base' dataset has multiple sub-bricks, all of them are used.\n"
             "\n"
             "* You can use the '-base' option more than once, if desired or needed.\n"
             "\n"
             "* The original motivation for this program was to fit a spatial model\n"
             "  to a field map MRI, but that didn't turn out to be useful. Nevertheless,\n"
             "  I make this program available to someone who might find it beguiling.\n"
             "\n"
             "* If you really want, I could allow you to put sign constraints on the\n"
             "  fit coefficients (e.g., say that the coefficient for a given base volume\n"
             "  should be non-negative). But you'll have to beg for this.\n"
             "\n"
             "-- Emitted by RWCox\n"
            ) ;
      PRINT_COMPILE_DATE ; exit(0) ;
   }

   /*-- startup paperwork --*/

   mainENTRY("3dPolyfit main"); machdep(); AFNI_logger("3dPolyfit",argc,argv);
   PRINT_VERSION("3dPolyfit") ;

   /*-- scan command line --*/

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

     if( strcasecmp(argv[iarg],"-base") == 0 ){
       THD_3dim_dataset *bset ; int kk ; MRI_IMAGE *bim ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-base'") ;
       bset = THD_open_dataset(argv[iarg]) ;
       CHECK_OPEN_ERROR(bset,argv[iarg]) ;
       DSET_load(bset) ; CHECK_LOAD_ERROR(bset) ;
       if( exar == NULL ) INIT_IMARR(exar) ;
       for( kk=0 ; kk < DSET_NVALS(bset) ; kk++ ){
         bim = THD_extract_float_brick(kk,bset) ;
         if( bim != NULL ) ADDTO_IMARR(exar,bim) ;
         DSET_unload_one(bset,kk) ;
       }
       DSET_delete(bset) ;
       iarg++ ; continue ;
     }

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

     if( strcasecmp(argv[iarg],"-hermite") == 0 ){ /* 25 Mar 2013 [New Year's Day] */
       mri_polyfit_set_basis("hermite") ;          /* HIDDEN */
       iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-byslice") == 0 ){ /* 25 Mar 2013 [New Year's Day] */
       do_byslice++ ; iarg++ ; continue ;          /* HIDDEN */
     }

     if( strcasecmp(argv[iarg],"-mask") == 0 ){
       THD_3dim_dataset *mset ;
       if( ++iarg >= 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[iarg]) ;
       CHECK_OPEN_ERROR(mset,argv[iarg]) ;
       DSET_load(mset) ; CHECK_LOAD_ERROR(mset) ;
       nvmask = DSET_NVOX(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]) ;
       nmask = THD_countmask( nvmask , mask ) ;
       if( nmask < 99 ) ERROR_exit("Too few voxels in mask (%d)",nmask) ;
       if( verb ) INFO_message("Number of voxels in mask = %d",nmask) ;
       iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-nord") == 0 ){
       nord = (int)strtol( argv[++iarg], NULL , 10 ) ;
       if( nord < -1 || nord > 9 )
         ERROR_exit("Illegal value after -nord :(") ;
       iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-meth") == 0 ){
       meth = (int)strtol( argv[++iarg], NULL , 10 ) ;
       if( meth < 1 || meth > 2 )
         ERROR_exit("Illegal value after -meth :(") ;
       iarg++ ; continue ;
     }

     if( strncmp(argv[iarg],"-automask",5) == 0 ){
       if( mask != NULL ) ERROR_exit("Can't use -mask and -automask together!") ;
       do_automask++ ; iarg++ ; continue ;
     }

     if( strncmp(argv[iarg],"-mclip",5) == 0 ){
       do_mclip++ ; iarg++ ; continue ;
     }

     if( strncmp(argv[iarg],"-mone",5) == 0 ){
       do_mone++ ; iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-mrad") == 0 ){
       mrad = strtod( argv[++iarg] , NULL ) ; iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-blur") == 0 ){
       fwhm = strtod( argv[++iarg] , NULL ) ; iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-prefix") == 0 ){
       prefix = argv[++iarg] ;
       if( !THD_filename_ok(prefix) )
         ERROR_exit("Illegal value after -prefix :(");
       if( strcasecmp(prefix,"NULL") == 0 ) prefix = NULL ;
       iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-resid") == 0 ){
       resid = argv[++iarg] ;
       if( !THD_filename_ok(resid) )
         ERROR_exit("Illegal value after -resid :(");
       if( strcasecmp(resid,"NULL") == 0 ) resid = NULL ;
       iarg++ ; continue ;
     }

     if( strcasecmp(argv[iarg],"-1Dcoef") == 0 ){  /* 26 Feb 2019 */
       cfnam = argv[++iarg] ;
       if( !THD_filename_ok(cfnam) )
         ERROR_exit("Illegal value after -1Dcoef :(");
       if( strcasecmp(cfnam,"NULL") == 0 ) cfnam = NULL ;
       iarg++ ; continue ;
     }

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

   /*--- check for blatant errors ---*/

   if( iarg >= argc )
     ERROR_exit("No input dataset name on command line?");

   if( prefix == NULL && resid == NULL && cfnam == NULL )
     ERROR_exit("-prefix and -resid and -1Dcoef are all NULL?!") ;

   if( do_byslice && cfnam != NULL ){
     WARNING_message("-byslice does not work with -1Dcoef option :(") ;
     cfnam = NULL ;
   }

   if( nord < 0 && exar == NULL )
     ERROR_exit("no polynomial fit AND no -base option ==> nothing to compute :(") ;

   /*-- read input --*/

   if( verb ) INFO_message("Load input dataset") ;

   inset = THD_open_dataset( argv[iarg] ) ;
   CHECK_OPEN_ERROR(inset,argv[iarg]) ;
   DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ;
   if( DSET_NVALS(inset) > 1 )
     WARNING_message( "Only processing sub-brick #0 (out of %d)" , DSET_NVALS(inset) );

   /* check input mask or create automask */

   if( mask != NULL ){
     if( nvmask != DSET_NVOX(inset) )
      ERROR_exit("-mask and input datasets don't match in voxel counts :-(") ;
   } else if( do_automask ){
     THD_automask_verbose( (verb > 1) ) ;
     THD_automask_extclip( 1 ) ;
     mask = THD_automask( inset ) ; nvmask = DSET_NVOX(inset) ;
     nmask = THD_countmask( nvmask , mask ) ;
     if( nmask < 99 ) ERROR_exit("Too few voxels in automask (%d)",nmask) ;
     if( verb ) ININFO_message("Number of voxels in automask = %d",nmask) ;
   } else {
     WARNING_message("3dPolyfit is running without a mask") ;
   }

#undef  GOOD
#define GOOD(i) (mask == NULL || mask[i])

   /* check -base input datasets */

   if( exar != NULL ){
     int ii,kk , nvbad=0 , nvox=DSET_NVOX(inset),nm ; float *ex , exb ;
     for( kk=0 ; kk < IMARR_COUNT(exar) ; kk++ ){
       if( nvox != IMARR_SUBIM(exar,kk)->nvox ){
         if( IMARR_SUBIM(exar,kk)->nvox != nvbad ){
           ERROR_message("-base volume (%d voxels) doesn't match input dataset grid size (%d voxels)",
                         IMARR_SUBIM(exar,kk)->nvox , nvox ) ;
           nvbad = IMARR_SUBIM(exar,kk)->nvox ;
         }
       }
     }
     if( nvbad != 0 ) ERROR_exit("Cannot continue :-(") ;

     /* subtract mean from each base input, if is a constant polynomial in the fit */

     if( nord >= 0 ){
       if( verb ) INFO_message("subtracting spatial mean from '-base'") ;
       for( kk=0 ; kk < IMARR_COUNT(exar) ; kk++ ){
         exb = 0.0f ; ex = MRI_FLOAT_PTR(IMARR_SUBIM(exar,kk)) ;
         for( nm=ii=0 ; ii < nvox ; ii++ ){ if( GOOD(ii) ){ exb += ex[ii]; nm++; } }
         exb /= nm ;
         for( ii=0 ; ii < nvox ; ii++ ) ex[ii] -= exb ;
       }
     }
   }

   /* if blurring, edit mask a little */

   if( mask != NULL && (fwhm > 0.0f || mrad > 0.0f) ){
     int ii ;
     ii = THD_mask_remove_isolas( DSET_NX(inset),DSET_NY(inset),DSET_NZ(inset),mask ) ;
     if( ii > 0 ){
       nmask = THD_countmask( nvmask , mask ) ;
       if( verb )
         ININFO_message("Removed %d isola%s from mask, leaving %d voxels" ,
                        ii,(ii==1)?"\0":"s" , nmask ) ;
       if( nmask < 99 )
         ERROR_exit("Too few voxels left in mask after isola removal :-(") ;
     }
   }

   /* convert input to float, which is simpler to deal with */

   imin = THD_extract_float_brick(0,inset) ;
   if( imin == NULL ) ERROR_exit("Can't extract input dataset brick?! :-(") ;
   DSET_unload(inset) ;

   if( verb ) INFO_message("Start fitting process") ;

   /* do the Gaussian blurring */

   if( fwhm > 0.0f ){
     if( verb ) ININFO_message("Gaussian blur: FWHM=%g mm",fwhm) ;
     imin->dx = fabsf(DSET_DX(inset)) ;
     imin->dy = fabsf(DSET_DY(inset)) ;
     imin->dz = fabsf(DSET_DZ(inset)) ;
     mri_blur3D_addfwhm( imin , mask , fwhm ) ;
   }

   /* do the fitting */

   mri_polyfit_verb(verb) ;
   if( do_byslice )
     imout = mri_polyfit_byslice( imin , nord , exar , mask , mrad , meth ) ;
   else
     imout = mri_polyfit        ( imin , nord , exar , mask , mrad , meth ) ;

   /* WTF? */

   if( imout == NULL )
     ERROR_exit("Can't compute polynomial fit :-( !?") ;
   if( resid == NULL ) mri_free(imin) ;

   if( ! do_byslice )
     fvit = mri_polyfit_get_fitvec() ; /* get coefficients of fit [26 Feb 2019] */

   /* scale the fit dataset? */

   if( do_mone ){
     float sum=0.0f ; int nsum=0 , ii,nvox ; float *par=MRI_FLOAT_PTR(imout) ;
     nvox = imout->nvox ;
     for( ii=0 ; ii < nvox ; ii++ ){
       if( mask != NULL && mask[ii] == 0 ) continue ;
       sum += par[ii] ; nsum++ ;
     }
     if( nsum > 0 && sum != 0.0f ){
       sum = nsum / sum ;
       if( verb ) ININFO_message("-mone: scaling fit by %g",sum) ;
       for( ii=0 ; ii < nvox ; ii++ ) par[ii] *= sum ;
     }
   }

   /* if there's a mask, clip values outside of its box */

#undef  PF
#define PF(i,j,k) par[(i)+(j)*nx+(k)*nxy]
   if( mask != NULL && do_mclip ){
     int xm,xp,ym,yp,zm,zp , ii,jj,kk , nx,ny,nz,nxy ; float *par ;
     MRI_IMAGE *bim = mri_empty_conforming( imout , MRI_byte ) ;
     mri_fix_data_pointer(mask,bim) ;
     if( verb ) ININFO_message("-mclip: polynomial fit to autobox of mask") ;
     MRI_autobbox( bim , &xm,&xp , &ym,&yp , &zm,&zp ) ;
     mri_clear_data_pointer(bim) ; mri_free(bim) ;
     nx = imout->nx ; ny = imout->ny ; nz = imout->nz ; nxy = nx*ny ;
     par = MRI_FLOAT_PTR(imout) ;
     for( ii=0 ; ii < xm ; ii++ )
      for( kk=0 ; kk < nz ; kk++ )
       for( jj=0 ; jj < ny ; jj++ ) PF(ii,jj,kk) = PF(xm,jj,kk) ;
     for( ii=xp+1 ; ii < nx ; ii++ )
      for( kk=0 ; kk < nz ; kk++ )
       for( jj=0 ; jj < ny ; jj++ ) PF(ii,jj,kk) = PF(xp,jj,kk) ;
     for( jj=0 ; jj < ym ; jj++ )
      for( kk=0 ; kk < nz ; kk++ )
       for( ii=0 ; ii < nx ; ii++ ) PF(ii,jj,kk) = PF(ii,ym,kk) ;
     for( jj=yp+1 ; jj < ny ; jj++ )
      for( kk=0 ; kk < nz ; kk++ )
       for( ii=0 ; ii < nx ; ii++ ) PF(ii,jj,kk) = PF(ii,yp,kk) ;
     for( kk=0 ; kk < zm ; kk++ )
      for( jj=0 ; jj < ny ; jj++ )
       for( ii=0 ; ii < nx ; ii++ ) PF(ii,jj,kk) = PF(ii,jj,zm) ;
     for( kk=zp+1 ; kk < nz ; kk++ )
      for( jj=0 ; jj < ny ; jj++ )
       for( ii=0 ; ii < nx ; ii++ ) PF(ii,jj,kk) = PF(ii,jj,zp) ;
   }

   if( mask != NULL ) free(mask) ;

   /* write outputs */

   if( prefix != NULL ){
     THD_3dim_dataset *outset = EDIT_empty_copy( inset )  ;
     EDIT_dset_items( outset ,
                        ADN_prefix , prefix ,
                        ADN_nvals  , 1 ,
                        ADN_ntt    , 0 ,
                      ADN_none ) ;
     EDIT_substitute_brick( outset , 0 , MRI_float , MRI_FLOAT_PTR(imout) ) ;
     tross_Copy_History( inset , outset ) ;
     tross_Make_History( "3dPolyfit" , argc,argv , outset ) ;
     DSET_write(outset) ;
     WROTE_DSET(outset) ;
   }

   if( resid != NULL ){
     THD_3dim_dataset *outset = EDIT_empty_copy( inset )  ;
     float *inar=MRI_FLOAT_PTR(imin) , *outar=MRI_FLOAT_PTR(imout) ;
     int nx,ny,nz , nxyz , kk ;
     nx = imout->nx ; ny = imout->ny ; nz = imout->nz ; nxyz = nx*ny*nz ;
     for( kk=0 ; kk < nxyz ; kk++ ) outar[kk] = inar[kk] - outar[kk] ;
     mri_free(imin) ;
     EDIT_dset_items( outset ,
                        ADN_prefix , resid ,
                        ADN_nvals  , 1 ,
                        ADN_ntt    , 0 ,
                      ADN_none ) ;
     EDIT_substitute_brick( outset , 0 , MRI_float , MRI_FLOAT_PTR(imout) ) ;
     tross_Copy_History( inset , outset ) ;
     tross_Make_History( "3dPolyfit" , argc,argv , outset ) ;
     DSET_write(outset) ;
     WROTE_DSET(outset) ;
   }

   if( cfnam != NULL && fvit != NULL ){ /* won't work with '-byslice' */
     char *qn ;
     qn = STRING_HAS_SUFFIX(cfnam,".1D") ? cfnam : modify_afni_prefix(cfnam,NULL,".1D") ;
     mri_write_floatvec( qn , fvit ) ;
   }

   exit(0) ;
}
Exemplo n.º 21
0
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) ;
}
Exemplo n.º 22
0
int main( int argc , char *argv[] )
{
   MRI_IMAGE *xim , *yim ;
   float     *xar , *yar , *war ;
   int iarg , ndset , nvox , ii , jj, xyall , clip=0 ;
   THD_3dim_dataset *xset , *yset , * mask_dset=NULL ;
   float xbot=1.0f,xtop=0.0f , ybot=1.0f,ytop=0.0f , val ;
   float xsum,ysum , xsig,ysig ;
   byte *mmm=NULL ;
   char *save_hist=NULL, *save_hist_1D=NULL ;

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

   if( argc < 3 || strncmp(argv[1],"-help",5) == 0 ){
     printf("Usage: 3dAcost [options] xset yset\n"
            "Output = 3dAllineate cost functions between 2 dataset bricks\n"
            "         (for debugging purposes, mostly).\n"
            "\n"
            "Options:\n"
            "  -mask mset   Means to use the dataset 'mset' as a mask:\n"
            "                 Only voxels with nonzero values in 'mset'\n"
            "                 will be averaged from 'dataset'.  Note\n"
            "                 that the mask dataset and the input dataset\n"
            "                 must have the same number of voxels.\n"
            " -histpow p    Set histogram power to 'p'; number of bins in\n"
            "                 histogram (each axis) = n^p (n=# of points).\n"
            "                 (Default is p=0.33333.)\n"
            " -histbin m    Set histogram to use 'm' bins (each axis).\n"
            "                 (Max number of bins is 255.)\n"
            " -savehist ss  Save 2D histogram to image file 'ss'\n"
            "                 (floating point image; read with 'afni -im')\n"
            " -savehist_1D dd  Save original form of 2D histogram to 1D file 'dd'\n"
            "                 (-savehist produces the rootogram)\n"
            " -xrange a b   Use only xset values in range a..b.\n"
            " -yrange c d   Use only yset values in range c..d.\n"
            "                 (Default is to use all values.)\n"
            " -clip         Use values from min to mri_topclip()\n"
           ) ;
     exit(0) ;
   }

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

     if( strcmp(argv[iarg],"-xrange") == 0 ){
       if( ++iarg >= argc-1 ) ERROR_exit("no arguments after '%s'!",argv[iarg-1]) ;
       xbot = (float)strtod(argv[iarg++],NULL) ;
       xtop = (float)strtod(argv[iarg++],NULL) ;
       continue ;
     }

     if( strcmp(argv[iarg],"-yrange") == 0 ){
       if( ++iarg >= argc-1 ) ERROR_exit("no arguments after '%s'!",argv[iarg-1]) ;
       ybot = (float)strtod(argv[iarg++],NULL) ;
       ytop = (float)strtod(argv[iarg++],NULL) ;
       continue ;
     }

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

     if( strcmp(argv[iarg],"-savehist") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("no argument after '%s'!",argv[iarg-1]) ;
       if( !THD_filename_ok(argv[iarg]) )
         ERROR_exit("badly formed filename: '%s' '%s'",argv[iarg-1],argv[iarg]);
       save_hist = argv[iarg] ; iarg++ ; continue ;
     }
     
     if( strcmp(argv[iarg],"-savehist_1D") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("no argument after '%s'!",argv[iarg-1]) ;
       save_hist_1D= argv[iarg] ; iarg++ ; continue ;
     }
     
     if( strcmp(argv[iarg],"-histpow") == 0 ){
       double hist_pow ;
       if( ++iarg >= argc ) ERROR_exit("no argument after '%s'!",argv[iarg-1]) ;
       hist_pow = strtod(argv[iarg],NULL) ;
       set_2Dhist_hpower(hist_pow) ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-histbin") == 0 ){
       int hist_nbin ;
       if( ++iarg >= argc ) ERROR_exit("no argument after '%s'!",argv[iarg-1]) ;
       hist_nbin = (int)strtod(argv[iarg],NULL) ;
       set_2Dhist_hbin(hist_nbin) ;
       iarg++ ; continue ;
     }

     if( strncmp(argv[iarg],"-mask",5) == 0 ){
       if( mask_dset != NULL ) ERROR_exit("Can't use -mask twice!") ;
       if( iarg+1 >= argc ) ERROR_exit("-mask needs a filename!") ;
       mask_dset = THD_open_dataset( argv[++iarg] ) ;
       CHECK_OPEN_ERROR(mask_dset,argv[iarg]) ;
       iarg++ ; continue ;
     }

     fprintf(stderr,"*** Unknown option: %s\n",argv[iarg]) ; exit(1) ;
   }

   /* should have at least 2 more arguments */

   ndset = argc - iarg ;
   if( ndset <= 1 ){
      fprintf(stderr,"*** No input datasets!?\n") ; exit(1) ;
   }

   xset = THD_open_dataset(argv[iarg++]) ; CHECK_OPEN_ERROR(xset,argv[iarg-1]) ;
   yset = THD_open_dataset(argv[iarg++]) ; CHECK_OPEN_ERROR(yset,argv[iarg-1]) ;
   DSET_load(xset) ; DSET_load(yset) ;
   CHECK_LOAD_ERROR(xset) ; CHECK_LOAD_ERROR(yset) ;
   if( DSET_NVALS(xset) > 1 || DSET_NVALS(yset) > 1 )
     WARNING_message("Using only sub-brick [0] of input datasets") ;

   nvox = DSET_NVOX(xset) ;
   if( nvox != DSET_NVOX(yset) )
     ERROR_exit("Input datasets dimensions don't match!") ;

   xim = mri_scale_to_float( DSET_BRICK_FACTOR(xset,0) , DSET_BRICK(xset,0) );
   yim = mri_scale_to_float( DSET_BRICK_FACTOR(yset,0) , DSET_BRICK(yset,0) );
   xar = MRI_FLOAT_PTR(xim) ; yar = MRI_FLOAT_PTR(yim) ;

   DSET_unload(xset); DSET_unload(yset);

   /* make a byte mask from mask dataset */

   war = (float *)malloc(sizeof(float)*nvox) ;
   if( mask_dset != NULL ){
     int mcount ;
     if( DSET_NVOX(mask_dset) != nvox )
       ERROR_exit("Input and mask datasets are not same dimensions!");

     mmm = THD_makemask( mask_dset , 0 , 666.0,-666.0 ) ;
     mcount = THD_countmask( nvox , mmm ) ;
     if( mcount <= 5 ) ERROR_exit("Mask is too small: %d voxels",mcount) ;
     DSET_delete(mask_dset) ;
     for( ii=0 ; ii < nvox ; ii++ ) war[ii] = (float)mmm[ii] ;
     free((void *)mmm) ;
   } else {
     for( ii=0 ; ii < nvox ; ii++ ) war[ii] = 1.0f ;
   }

   if( clip ){
     xbot = mri_min(xim) ; xtop = mri_topclip(xim) ;
     INFO_message("xbot=%g  xclip=%g",xbot,xtop) ;
     ybot = mri_min(yim) ; ytop = mri_topclip(yim) ;
     INFO_message("ybot=%g  yclip=%g",ybot,ytop) ;
   }

   xyall = 0 ;
   if( xbot >= xtop ){
     xbot = 1.e+38 ; xtop = -1.e+38 ;
     for( ii=0 ; ii < nvox ; ii++ )
       if( war[ii] > 0.0f ){
              if( xar[ii] < xbot ) xbot = xar[ii] ;
         else if( xar[ii] > xtop ) xtop = xar[ii] ;
       }
     INFO_message("xbot=%g  xtop=%g",xbot,xtop) ;
     if( xbot >= xtop ) ERROR_exit("no x range?!") ;
     xyall++ ;
   }
   if( ybot >= ytop ){
     ybot = 1.e+38 ; ytop = -1.e+38 ;
     for( ii=0 ; ii < nvox ; ii++ )
       if( war[ii] > 0.0f ){
              if( yar[ii] < ybot ) ybot = yar[ii] ;
         else if( yar[ii] > ytop ) ytop = yar[ii] ;
       }
     INFO_message("ybot=%g  ytop=%g",ybot,ytop) ;
     if( ybot >= ytop ) ERROR_exit("no y range?!") ;
     xyall++ ;
   }
   if( xyall < 2 ){
     for( ii=0 ; ii < nvox ; ii++ )
       if( xar[ii] < xbot || xar[ii] > xtop ||
           yar[ii] < ybot || yar[ii] > ytop   ) war[ii] = 0.0f ;
   }
   xyall = 0 ;
   for( ii=0 ; ii < nvox ; ii++ ) xyall += (war[ii] > 0.0f) ;
   INFO_message("Processing %d voxels",xyall) ;
   if( xyall <= 5 ) ERROR_exit("Too few voxels to continue!") ;

   xsum = ysum = 0.0f ;
   for( ii=0 ; ii < nvox ; ii++ ){
     if( war[ii] > 0.0f ){ xsum += xar[ii]; ysum += yar[ii]; }
   }
   xsum /= xyall ; ysum /= xyall ;
   INFO_message("xmean=%g  ymean=%g",xsum,ysum) ;
   xsig = ysig = 0.0f ;
   for( ii=0 ; ii < nvox ; ii++ ){
     if( war[ii] > 0.0f ){
       val = (xar[ii]-xsum) ; xsig += val*val ;
       val = (yar[ii]-ysum) ; ysig += val*val ;
     }
   }
   xsig = sqrt( xsig/(xyall-1.0) ); ysig = sqrt( ysig/(xyall-1.0) );
   INFO_message("xsig =%g  ysig =%g",xsig,ysig) ;

   val = THD_pearson_corr_wt( nvox , xar , yar , war ) ;
   val = 1.0 - fabs(val) ;
   printf("1-Correlation     = %+.5f\n",val) ;

   val = -THD_mutual_info_scl( nvox , xbot,xtop,xar , ybot,ytop,yar , war ) ;
   printf("-Mutual Info      = %+.5f\n",val ) ;

   val = THD_norm_mutinf_scl( nvox , xbot,xtop,xar , ybot,ytop,yar , war ) ;
   printf("Norm Mutual Info  = %+.5f\n",val ) ;

#if 0
   INFO_message("THD_corr_ratio_scl(%d,%g,%g,xar,%g,%g,yar,war)",
                 nvox , xbot,xtop , ybot,ytop ) ;
#endif

   THD_corr_ratio_sym_mul ;
   val = THD_corr_ratio_scl( nvox , xbot,xtop,xar , ybot,ytop,yar , war ) ;
   val = 1.0 - fabs(val) ;
   printf("1-Corr ratio sym* = %+.5f\n",val) ;

   THD_corr_ratio_sym_add ;
   val = THD_corr_ratio_scl( nvox , xbot,xtop,xar , ybot,ytop,yar , war ) ;
   val = 1.0 - fabs(val) ;
   printf("1-Corr ratio sym+ = %+.5f\n",val) ;

   THD_corr_ratio_sym_not ;
   val = THD_corr_ratio_scl( nvox , xbot,xtop,xar , ybot,ytop,yar , war ) ;
   val = 1.0 - fabs(val) ;
   printf("1-Corr ratio unsym= %+.5f\n",val) ;

   val = -THD_hellinger_scl( nvox , xbot,xtop,xar , ybot,ytop,yar , war ) ;
   printf("-Hellinger metric = %+.5f\n",val) ;

   if( save_hist != NULL ){  /* Save 2D histogram */
     int nbin ; float *xyc ;
     nbin = retrieve_2Dhist( &xyc ) ;
     if( nbin > 0 && xyc != NULL ){
       MRI_IMAGE *fim,*qim ; double ftop ;
       fim = mri_new(nbin,nbin,MRI_float); mri_fix_data_pointer(xyc,fim);
#if 0
       for( ii=0 ; ii < nbin*nbin ; ii++ ) xyc[ii] = sqrtf(xyc[ii]) ;
       ftop = mri_max(fim); if( ftop == 0.0 ) ftop = 1.0;
       qim = mri_to_byte_scl(255.4/ftop,0.0,fim) ;
       mri_clear_data_pointer(fim); mri_free(fim);
       fim = mri_flippo(MRI_ROT_180,1,qim); mri_free(qim);
       mri_write_pnm(save_hist,fim); mri_free(fim);
#else
       qim = mri_flippo(MRI_ROT_180,1,fim);
       mri_clear_data_pointer(fim); mri_free(fim);
       mri_write(save_hist,qim); mri_free(qim);
#endif
       INFO_message("- Saved %dx%d histogram to %s",nbin,nbin,save_hist) ;
       
     }
   }
   
   if( save_hist_1D != NULL ){  /* Save 2D raw histogram */
     int nbin ; float *xyc ;
     nbin = retrieve_2Dhist( &xyc ) ;
     if( nbin > 0 && xyc != NULL ){
         FILE *fid=fopen(save_hist_1D,"w");
         for( ii=0 ; ii < nbin; ii++ ) {
            for( jj=0 ; jj < nbin; jj++ ) {
               fprintf(fid,"%.4f\t", xyc[ii*nbin+jj]); 
            }
            fprintf(fid,"\n");
         }
         fclose(fid);
      }
      INFO_message("- Saved %dx%d 1D histogram to %s",nbin,nbin,save_hist_1D) ;
       
  }
  
   exit(0) ;
}
Exemplo n.º 23
0
static int * PLUTO_4D_to_nothing (THD_3dim_dataset * old_dset , int ignore , int detrend ,
                         generic_func * user_func, void * user_data )
{

   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) */
   complex ** cptr = NULL ;

   float * fxar = NULL ;  /* array loaded from input dataset */
   float * fac  = NULL ;  /* array of brick scaling factors */
   float * dtr  = NULL ;  /* will be array of detrending coeff */

   float val , d0fac , d1fac , x0,x1;
   double tzero=0.0 , tdelta , ts_mean , ts_slope ;
   int   ii , old_datum , nuse , use_fac , iz,izold, nxy,nvox ;
   static int retval;
	register int kk ;

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

   if( ! ISVALID_3DIM_DATASET(old_dset) ) return NULL ;

   if( user_func == NULL ) return NULL ;

   if( ignore < 0 ) ignore = 0 ;

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

   old_datum = DSET_BRICK_TYPE( old_dset , 0 ) ;   /* get old dataset datum */
   nuse      = DSET_NUM_TIMES(old_dset) - ignore ; /* # of points on time axis */
   if( nuse < 2 ) return NULL ;

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

   kk = THD_count_databricks( old_dset->dblk ) ;  /* check if it was */
   if( kk < DSET_NVALS(old_dset) ){               /* loaded correctly */
      DSET_unload( old_dset ) ;
      return NULL ;
   }

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

      default:                      /** don't know what to do **/
         DSET_unload( old_dset ) ;
         return NULL ;

      /** create array of pointers into old dataset sub-bricks **/

      /*--------- 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 NULL ;
         for( kk=0 ; kk < nuse ; kk++ )
            bptr[kk] = (byte *) DSET_ARRAY(old_dset,kk+ignore) ;
      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 NULL ;
         for( kk=0 ; kk < nuse ; kk++ )
            sptr[kk] = (short *) DSET_ARRAY(old_dset,kk+ignore) ;
      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 NULL ;
         for( kk=0 ; kk < nuse ; kk++ )
            fptr[kk] = (float *) DSET_ARRAY(old_dset,kk+ignore) ;
      break ;

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

      case MRI_complex:
         cptr = (complex **) malloc( sizeof(complex *) * nuse ) ;
         if( cptr == NULL ) return NULL ;
         for( kk=0 ; kk < nuse ; kk++ )
            cptr[kk] = (complex *) DSET_ARRAY(old_dset,kk+ignore) ;
      break ;

   } /* end of switch on input type */

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

   
   /*---- allocate space for 1 voxel timeseries ----*/

   fxar = (float *) malloc( sizeof(float) * nuse ) ;   /* voxel timeseries */
   if( fxar == NULL ){ ZFREE_WORKSPACE ; return NULL ; }

   /*--- get scaling factors for sub-bricks ---*/

   fac = (float *) malloc( sizeof(float) * nuse ) ;   /* factors */
   if( fac == NULL ){ ZFREE_WORKSPACE ; return NULL ; }

   use_fac = 0 ;
   for( kk=0 ; kk < nuse ; kk++ ){
      fac[kk] = DSET_BRICK_FACTOR(old_dset,kk+ignore) ;
      if( fac[kk] != 0.0 ) use_fac++ ;
      else                 fac[kk] = 1.0 ;
   }
   if( !use_fac ) ZFREEUP(fac) ;

   /*--- setup for detrending ---*/

   dtr = (float *) malloc( sizeof(float) * nuse ) ;
   if( dtr == NULL ){ ZFREE_WORKSPACE ; return NULL ; }

   d0fac = 1.0 / nuse ;
   d1fac = 12.0 / nuse / (nuse*nuse - 1.0) ;
   for( kk=0 ; kk < nuse ; kk++ )
      dtr[kk] = kk - 0.5 * (nuse-1) ;  /* linear trend, orthogonal to 1 */


   /*----- set up to find time at each voxel -----*/

   tdelta = old_dset->taxis->ttdel ;
   if( DSET_TIMEUNITS(old_dset) == UNITS_MSEC_TYPE ) tdelta *= 0.001 ;
   if( tdelta == 0.0 ) tdelta = 1.0 ;

   izold  = -666 ;
   nxy    = old_dset->daxes->nxx * old_dset->daxes->nyy ;

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

   /* start notification */
#if 0
   user_func(  0.0 , 0.0 , nvox , NULL,0.0,0.0 , user_data ) ;
#else
   { void (*uf)(double,double,int,float *,double,double,void *) =
     (void (*)(double,double,int,float *,double,double,void *))(user_func) ;
     uf( 0.0l,0.0l , nvox , NULL , 0.0l,0.0l , user_data ) ;
   }
#endif

   /***** loop over voxels *****/   
   for( ii=0 ; ii < nvox ; ii++  ){  /* 1 time series at a time */
		
      /*** load data from input dataset, depending on type ***/

      switch( old_datum ){

         /*** input = bytes ***/

         case MRI_byte:
            for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] = bptr[kk][ii] ;
         break ;

         /*** input = shorts ***/

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

         /*** input = floats ***/

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

         /*** input = complex (note we use absolute value) ***/

         case MRI_complex:
            for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] = CABS(cptr[kk][ii]) ;
         break ;

      } /* end of switch over input type */

      /*** scale? ***/
     if( use_fac )
         for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] *= fac[kk] ;

      /** compute mean and slope **/

      x0 = x1 = 0.0 ;
      for( kk=0 ; kk < nuse ; kk++ ){
         x0 += fxar[kk] ; x1 += fxar[kk] * dtr[kk] ;
      }

      x0 *= d0fac ; x1 *= d1fac ;  /* factors to remove mean and trend */

      ts_mean  = x0 ;
      ts_slope = x1 / tdelta ;
 
      /** detrend? **/

      if( detrend )
         for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] -= (x0 + x1 * dtr[kk]) ;

      /** compute start time of this timeseries **/
		/* The info computed here is not being used in this version*/
      iz = ii / nxy ;    /* which slice am I in? */

      if( iz != izold ){          /* in a new slice? */
         tzero = THD_timeof( ignore ,
                             old_dset->daxes->zzorg
                           + iz*old_dset->daxes->zzdel , old_dset->taxis ) ;
         izold = iz ;

         if( DSET_TIMEUNITS(old_dset) == UNITS_MSEC_TYPE ) tzero *= 0.001 ;
      }

      /*** Send data to user function ***/
#if 0
      user_func( tzero,tdelta , nuse,fxar,ts_mean,ts_slope , user_data) ;
#else
     { void (*uf)(double,double,int,float *,double,double,void *) =
       (void (*)(double,double,int,float *,double,double,void *))(user_func) ;
       uf( tzero,tdelta , nuse,fxar,ts_mean,ts_slope , user_data) ;
     }
#endif

      

   } /* end of outer loop over 1 voxels at a time */

   DSET_unload( old_dset ) ;  

   /* end notification */
#if 0
   user_func( 0.0 , 0.0 , 0 , NULL,0.0,0.0 , user_data ) ;
#else
   { void (*uf)(double,double,int,float *,double,double,void *) =
     (void (*)(double,double,int,float *,double,double,void *))(user_func) ;
     uf( 0.0l,0.0l, 0 , NULL,0.0l,0.0l, user_data ) ;
   }
#endif

   
   /*-------------- Cleanup and go home ----------------*/
   
   ZFREE_WORKSPACE ;
	retval = 0;
	return &retval; /* this value is not used for now .... */

}
Exemplo n.º 24
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) ;
}
Exemplo n.º 25
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) ;
}
Exemplo n.º 26
0
int main( int argc , char * argv[] )
{
   void (*smth)(int,float *) = linear3_func ;     /* default filter */

   char prefix[256] = "smooth" ;
   int new_datum = ILLEGAL_TYPE , old_datum ;
   int nopt ;
   THD_3dim_dataset * old_dset , * new_dset ;
   int ii,kk , nxyz , ntime , use_fac , ityp , nbytes ;
   void * new_brick ;

   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) */

   byte  ** new_bptr = NULL ;  /* one of these will be the array of */
   short ** new_sptr = NULL ;  /* pointers to output dataset sub-bricks */
   float ** new_fptr = NULL ;  /* (depending on output datum type) */

   float * fxar = NULL ;  /* array loaded from input dataset */
   float * fac  = NULL ;  /* array of brick scaling factors */
   float * faci = NULL ;

#define BLACKMAN 1
#define HAMMING  2
#define CUSTOM   3

#define EXTEND   77
#define ZERO     78
#define TREND    79

   int ntap=0 ;      /* 01 Mar 2001 */
   float *ftap=NULL ;
   int nwin=0,nfil=EXTEND ;      /* 03 Mar 2001 */

   void (*lfil)(int,float *,int,float *) = linear_filter_extend ;
   float * (*lwin)(int) = NULL ;

   /* start of code */

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
      printf("Usage: 3dTsmooth [options] dataset\n"
             "Smooths each voxel time series in a 3D+time dataset and produces\n"
             "as output a new 3D+time dataset (e.g., lowpass filter in time).\n"
             "\n"
             "*** Also see program 3dBandpass ***\n"
             "\n"
             "General Options:\n"
             "  -prefix ppp  = Sets the prefix of the output dataset to be 'ppp'.\n"
             "                   [default = 'smooth']\n"
             "  -datum type  = Coerce output dataset to be stored as the given type.\n"
             "                   [default = input data type]\n"
             "\n"
             "Three Point Filtering Options [07 July 1999]\n"
             "--------------------------------------------\n"
             "The following options define the smoothing filter to be used.\n"
             "All these filters  use 3 input points to compute one output point:\n"
             "  Let a = input value before the current point\n"
             "      b = input value at the current point\n"
             "      c = input value after the current point\n"
             "           [at the left end, a=b; at the right end, c=b]\n"
             "\n"
             "  -lin = 3 point linear filter: 0.15*a + 0.70*b + 0.15*c\n"
             "           [This is the default smoother]\n"
             "  -med = 3 point median filter: median(a,b,c)\n"
             "  -osf = 3 point order statistics filter:\n"
             "           0.15*min(a,b,c) + 0.70*median(a,b,c) + 0.15*max(a,b,c)\n"
             "\n"
             "  -3lin m = 3 point linear filter: 0.5*(1-m)*a + m*b + 0.5*(1-m)*c\n"
             "              Here, 'm' is a number strictly between 0 and 1.\n"
             "\n"
             "General Linear Filtering Options [03 Mar 2001]\n"
             "----------------------------------------------\n"
             "  -hamming N  = Use N point Hamming or Blackman windows.\n"
             "  -blackman N     (N must be odd and bigger than 1.)\n"
             "  -custom coeff_filename.1D (odd # of coefficients must be in a \n"
	     "                             single column in ASCII file)\n"
	     "   (-custom added Jan 2003)\n"
             "    WARNING: If you use long filters, you do NOT want to include the\n"
             "             large early images in the program.  Do something like\n"
             "                3dTsmooth -hamming 13 'fred+orig[4..$]'\n"
             "             to eliminate the first 4 images (say).\n"
             " The following options determing how the general filters treat\n"
             " time points before the beginning and after the end:\n"
             "  -EXTEND = BEFORE: use the first value; AFTER: use the last value\n"
             "  -ZERO   = BEFORE and AFTER: use zero\n"
             "  -TREND  = compute a linear trend, and extrapolate BEFORE and AFTER\n"
             " The default is -EXTEND.  These options do NOT affect the operation\n"
             " of the 3 point filters described above, which always use -EXTEND.\n"
           ) ;
      printf("\n" MASTER_SHORTHELP_STRING ) ;
      PRINT_COMPILE_DATE ; exit(0) ;
   }

   mainENTRY("3dTsmooth main"); machdep(); AFNI_logger("3dTsmooth",argc,argv);
   PRINT_VERSION("3dTsmooth") ;

   /* parse options */

   nopt = 1 ;

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

      if( strcmp(argv[nopt],"-EXTEND") == 0 ){         /* 03 Mar 2001 */
         nfil = EXTEND ; lfil = linear_filter_extend ;
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-ZERO") == 0 ){           /* 03 Mar 2001 */
         nfil = ZERO ; lfil = linear_filter_zero ;
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-TREND") == 0 ){          /* 03 Mar 2001 */
         nfil = TREND ; lfil = linear_filter_trend ;
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-hamming") == 0 ){
         if( ++nopt >= argc ){fprintf(stderr,"*** Illegal -hamming!\n");exit(1);}
         ntap = (int) strtod(argv[nopt],NULL) ;
         if( ntap < 3 || ntap%2 != 1 ){fprintf(stderr,"*** Illegal -hamming!\n");exit(1);}
         nwin = HAMMING ; lwin = hamming_window ;
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-blackman") == 0 ){
         if( ++nopt >= argc ){fprintf(stderr,"*** Illegal -blackman!\n");exit(1);}
         ntap = (int) strtod(argv[nopt],NULL) ;
         if( ntap < 3 || ntap%2 != 1 ){fprintf(stderr,"*** Illegal -blackman!\n");exit(1);}
         nwin = BLACKMAN ; lwin = blackman_window ;
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-custom") == 0 ){
         if( ++nopt >= argc ){fprintf(stderr,"*** Illegal -custom!\n");exit(1);}
         strcpy(custom_file, argv[nopt]) ;
         nwin = CUSTOM ; lwin = custom_filter ;
	 ntap = 1;
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-prefix") == 0 ){
         if( ++nopt >= argc ){fprintf(stderr,"*** Illegal -prefix!\n");exit(1);}
         strcpy(prefix,argv[nopt]) ;
         if( !THD_filename_ok(prefix) ){fprintf(stderr,"*** Illegal -prefix!\n");exit(1);}
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-datum") == 0 ){
         if( ++nopt >= argc ){fprintf(stderr,"*** Illegal -datum!\n");exit(1);}
         if( strcmp(argv[nopt],"short") == 0 ){
            new_datum = MRI_short ;
         } else if( strcmp(argv[nopt],"float") == 0 ){
            new_datum = MRI_float ;
         } else if( strcmp(argv[nopt],"byte") == 0 ){
            new_datum = MRI_byte ;
         } else {
            fprintf(stderr,"*** Illegal -datum!\n");exit(1);
         }
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-lin") == 0 ){
         bf = 0.70 ; af = cf = 0.15 ;
         smth = linear3_func ;
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-med") == 0 ){
         smth = median3_func ;
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-osf") == 0 ){
         smth = osfilt3_func ;
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-3lin") == 0 ){
         if( ++nopt >= argc ){fprintf(stderr,"*** Illegal -3lin!\n");exit(1);}
         bf = strtod( argv[nopt] , NULL ) ;
         if( bf <= 0.0 || bf >= 1.0 ){fprintf(stderr,"*** Illegal -3lin!\n");exit(1);}
         af = cf = 0.5*(1.0-bf) ;
         smth = linear3_func ;
         nopt++ ; continue ;
      }

      fprintf(stderr,"*** Unknown option: %s\n",argv[nopt]) ; exit(1) ;

   }  /* end of loop over options */

   if( nopt >= argc ){
      fprintf(stderr,"*** No input dataset?!\n") ; exit(1) ;
   }

   /* open dataset */

   old_dset = THD_open_dataset( argv[nopt] ) ;
   if( old_dset == NULL ){
      fprintf(stderr,"*** Can't open dataset %s\n",argv[nopt]) ; exit(1) ;
   }

   ntime = DSET_NVALS(old_dset) ;
   nxyz  = DSET_NVOX(old_dset) ;

   if( ntime < 4 ){
      fprintf(stderr,"*** Can't smooth dataset with less than 4 time points!\n") ;
      exit(1) ;
   }

   DSET_load(old_dset) ; CHECK_LOAD_ERROR(old_dset) ;

   old_datum = DSET_BRICK_TYPE(old_dset,0) ;
   if( new_datum < 0 ) new_datum = old_datum ;

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

      /** create array of pointers into old dataset sub-bricks **/

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

      case MRI_byte:
         bptr = (byte **) malloc( sizeof(byte *) * ntime ) ;
         for( kk=0 ; kk < ntime ; 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..nxyz-1 and k=0..ntime-1. */

      case MRI_short:
         sptr = (short **) malloc( sizeof(short *) * ntime ) ;
         for( kk=0 ; kk < ntime ; 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..nxyz-1 and k=0..ntime-1. */

      case MRI_float:
         fptr = (float **) malloc( sizeof(float *) * ntime ) ;
         for( kk=0 ; kk < ntime ; kk++ )
            fptr[kk] = (float *) DSET_ARRAY(old_dset,kk) ;
      break ;

   } /* end of switch on input type */

   /*---- allocate space for 1 voxel timeseries ----*/

   fxar = (float *) malloc( sizeof(float) * ntime ) ;   /* voxel timeseries */

   /*--- get scaling factors for sub-bricks ---*/

   fac = (float *) malloc( sizeof(float) * ntime ) ;   /* factors */

   use_fac = 0 ;
   for( kk=0 ; kk < ntime ; kk++ ){
      fac[kk] = DSET_BRICK_FACTOR(old_dset,kk) ;
      if( fac[kk] != 0.0 ) use_fac++ ;
      else                 fac[kk] = 1.0 ;
   }
   if( !use_fac ){
      free(fac) ; fac == NULL ;
   } else {
      faci = (float *) malloc( sizeof(float) * ntime ) ;
      for( kk=0 ; kk < ntime ; kk++ ) faci[kk] = 1.0 / fac[kk] ;
   }

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

   new_dset = EDIT_empty_copy( old_dset ) ;

   tross_Copy_History( old_dset , new_dset ) ;
   tross_Make_History( "3dTsmooth" , argc,argv , new_dset ) ;

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

   EDIT_dset_items( new_dset ,
                      ADN_prefix      , prefix ,
                      ADN_malloc_type , DATABLOCK_MEM_MALLOC ,
                      ADN_datum_all   , new_datum ,
                    ADN_none ) ;

   /*-- make brick(s) for this dataset --*/

   switch( new_datum ){
      case MRI_byte:
         new_bptr = (byte **) malloc( sizeof(byte *) * ntime ) ;
      break ;

      case MRI_short:
         new_sptr = (short **) malloc( sizeof(short *) * ntime ) ;
      break ;

      case MRI_float:
         new_fptr = (float **) malloc( sizeof(float *) * ntime ) ;
      break ;
   }

   for( kk=0 ; kk < ntime ; kk++ ){
      ityp      = DSET_BRICK_TYPE(new_dset,kk) ;   /* type of data */
      nbytes    = DSET_BRICK_BYTES(new_dset,kk) ;  /* how much data */
      new_brick = malloc( nbytes ) ;               /* make room */

      if( new_brick == NULL ){
        fprintf(stderr,"*** Can't get memory for output dataset!\n") ; exit(1) ;
      }

      EDIT_substitute_brick( new_dset , kk , ityp , new_brick ) ;

      switch( new_datum ){
         case MRI_byte:  new_bptr[kk] = (byte * ) new_brick ; break ;
         case MRI_short: new_sptr[kk] = (short *) new_brick ; break ;
         case MRI_float: new_fptr[kk] = (float *) new_brick ; break ;
      }
   }

   if( lwin != NULL && ntap > 0 ){        /* 03 Mar 2001 */
      ftap = lwin(ntap) ;
      if( lfil == NULL ) lfil = linear_filter_extend ;
      if( nwin == CUSTOM ) ntap = custom_ntaps ;
   }

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

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

   for( ii=0 ; ii < nxyz ; ii++  ){  /* 1 time series at a time */

      /*** load data from input dataset, depending on type ***/

      switch( old_datum ){
         case MRI_byte:
            for( kk=0 ; kk < ntime ; kk++ ) fxar[kk] = bptr[kk][ii] ;
         break ;

         case MRI_short:
            for( kk=0 ; kk < ntime ; kk++ ) fxar[kk] = sptr[kk][ii] ;
         break ;

         case MRI_float:
            for( kk=0 ; kk < ntime ; kk++ ) fxar[kk] = fptr[kk][ii] ;
         break ;
      } /* end of switch over input type */

      if( use_fac )
         for( kk=0 ; kk < ntime ; kk++ ) fxar[kk] *= fac[kk] ;

      /* do smoothing */

      if( ftap != NULL )
         lfil( ntap,ftap , ntime,fxar ) ;  /* 01 Mar 2001 */
      else
         smth( ntime , fxar ) ;            /* 3 point smoother */

      /*** put data into output dataset ***/

      switch( new_datum ){

         case MRI_byte:
            if( use_fac )
               for( kk=0 ; kk < ntime ; kk++ ) new_bptr[kk][ii] = (byte)(fxar[kk] * faci[kk]) ;
            else
               for( kk=0 ; kk < ntime ; kk++ ) new_bptr[kk][ii] = (byte) fxar[kk] ;
         break ;

         case MRI_short:
            if( use_fac )
               for( kk=0 ; kk < ntime ; kk++ ) new_sptr[kk][ii] = (short)(fxar[kk] * faci[kk]) ;
            else
               for( kk=0 ; kk < ntime ; kk++ ) new_sptr[kk][ii] = (short) fxar[kk] ;
         break ;

         case MRI_float:
            if( use_fac )
               for( kk=0 ; kk < ntime ; kk++ ) new_fptr[kk][ii] = (float)(fxar[kk] * faci[kk]) ;
            else
               for( kk=0 ; kk < ntime ; kk++ ) new_fptr[kk][ii] = (float) fxar[kk] ;
         break ;
      }
   }  /* end of loop over voxels */

   DSET_unload(old_dset) ; free(ftap) ;
   
   if (DSET_write(new_dset) != False) {
      fprintf(stderr,"++ output dataset: %s\n",DSET_BRIKNAME(new_dset)) ;
      exit(0) ;
   } else {
      fprintf(stderr,
         "** 3dTsmooth: Failed to write output!\n" ) ;
      exit(1) ;
   }            

}
Exemplo n.º 27
0
static char * CLUST_main( PLUGIN_interface * plint )
{
   char * tag , * new_prefix ;
   float rmm , vmul , thresh ;
   MCW_idcode * idc ;
   THD_3dim_dataset * dset , * new_dset ;
   int ival , ityp , nbytes , nvals ;
   EDIT_options edopt ;
   void * new_brick , * old_brick ;

   int clust_type;       /* input cluster type option */     /* 19 June 1998 */
   char * str;           /* input string */
   float pv;             /* pv % voxels within rmm must be active */
   int dilate;           /* boolean for perform dilation of cluster voxels */


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

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

   tag = PLUTO_get_optiontag(plint) ;
   if( tag==NULL || strcmp(tag,"Dataset") != 0 )
      return "**********************************\n"
             "CLUST_main: bad Dataset option tag\n"
             "**********************************"    ;

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

   tag = PLUTO_get_optiontag(plint) ;
   if( tag==NULL || strcmp(tag,"Params") != 0 )
      return "*********************************\n"
             "CLUST_main: bad Params option tag\n"
             "*********************************"   ;

   str = PLUTO_get_string(plint);                            /* 19 June 1998 */
   if (strcmp(str,"Keep") == 0)         clust_type = ECFLAG_SAME;
   else  if (strcmp(str,"Mean") == 0)   clust_type = ECFLAG_MEAN;
   else  if (strcmp(str,"Max") == 0)    clust_type = ECFLAG_MAX;
   else  if (strcmp(str,"AMax") == 0)   clust_type = ECFLAG_AMAX;
   else  if (strcmp(str,"SMax") == 0)   clust_type = ECFLAG_SMAX;
   else	 if (strcmp(str,"Size") == 0)   clust_type = ECFLAG_SIZE;
   else  if (strcmp(str,"Order") == 0)  clust_type = ECFLAG_ORDER;
   else  if (strcmp(str,"Depth") == 0)  clust_type = ECFLAG_DEPTH;
   else
     return 
       "**********************************\n"
       "CLUST_main: Illegal Cluster option\n"
       "**********************************";

   rmm  = PLUTO_get_number(plint) ;
   vmul = PLUTO_get_number(plint) ;
   if( rmm <= 0 || vmul <= 0 )
      return "****************************\n"
             "CLUST_main: bad Params input\n"
             "****************************"   ;


                                                             /* 19 June 1998 */
   tag = PLUTO_peek_optiontag(plint) ;
   if( tag != NULL && strcmp(tag,"Erode/Dilate") == 0 )
     {
       PLUTO_next_option(plint) ;
       pv  = PLUTO_get_number(plint);
       if ((pv > 0.0) && (rmm <= 0.0))
	 return 
	   "*******************************************************\n"
	   "CLUST_main: Erode/Dilate requires use of Cluster option\n"
	   "*******************************************************";
       else
	 pv  = pv / 100.0;
       
       str = PLUTO_get_string(plint);
       if (strcmp (str, "True") == 0)
	 {
	   if (pv <= 0.0)
	     return 
	       "***********************************************\n"
	       "CLUST_main: Dilate requires use of Erode option\n"
	       "***********************************************";
	   else
	     dilate = 1;
	 }
       else
	 dilate = 0;       
     }
   else
     {
       pv = 0.0;
       dilate = 0;
     }
   
   
   tag = PLUTO_peek_optiontag(plint) ;
   if( tag != NULL && strcmp(tag,"Threshold") == 0 ){
      PLUTO_next_option(plint) ;
      thresh = PLUTO_get_number(plint) ;
      if( thresh < 0.0 )
         return "*******************************\n"
                "CLUST_main: bad Threshold input\n"
                "*******************************"   ;

      if( thresh > 0.0 && DSET_THRESH_INDEX(dset) < 0 )
         return "**********************************************\n"
                "CLUST_main: Dataset has no threshold sub-brick\n"
                "**********************************************"  ;
   } else {
      thresh = 0.0 ;
   }

   tag = PLUTO_peek_optiontag(plint) ;
   if( tag != NULL && strcmp(tag,"Output") == 0 ){
      PLUTO_next_option(plint) ;
      new_prefix = PLUTO_get_string(plint) ;
      if( ! PLUTO_prefix_ok(new_prefix) )
         return "**********************\n"
                "CLUST_main: bad prefix\n"
                "**********************"   ;
   } else {
     new_prefix = NULL ;
   }

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

   /*-- maybe, make a new dataset --*/

   if( new_prefix == NULL ){  /* no prefix => edit input in place */

      new_dset = dset ;
      DSET_load( dset ) ;     /* load into memory */

   } else {                   /* OK, make a copy first */
      new_dset = PLUTO_copy_dset( dset , new_prefix ) ;

      if( new_dset == NULL )
         return  "****************************************\n"
                 "CLUST_main: failed to copy input dataset\n"
                 "****************************************"  ;

      DSET_unload( dset ) ;  /* unload from memory */
   }

   /*-- set up for dataset editing --*/

   INIT_EDOPT( &edopt ) ;

   edopt.edit_clust = clust_type;                            /* 19 June 1998 */

   edopt.clust_rmm  = rmm ;
   edopt.clust_vmul = vmul ;

   edopt.erode_pv = pv;
   edopt.dilate = dilate;

   if( thresh > 0.0 ) edopt.thresh = thresh ;

   /*-- edit the new dataset --*/

   EDIT_one_dataset( new_dset , &edopt ) ;

   /*-- if we made a completely new dataset, give it to AFNI --*/

   if( new_dset != dset ){
      ival = PLUTO_add_dset( plint , new_dset , DSET_ACTION_MAKE_CURRENT ) ;

      if( ival ){
        THD_delete_3dim_dataset( new_dset , False ) ;
        return "**********************************************\n"
               "CLUST_main: failure to add new dataset to AFNI\n"
               "**********************************************" ;
      }
   } else {
      DSET_overwrite( new_dset ) ;    /* otherwise, re-write to disk */
      PLUTO_force_redisplay() ;  /* and force a redisplay of images */
   }

   /*-- done successfully!!! --*/

   return NULL ;
}
Exemplo n.º 28
0
int main(int argc, char * argv[])
{
   char cphase1d[256] = "\0", rphase1d[256] = "\0";
   char new_prefix[THD_MAX_PREFIX] = TRIC_O_DEF_NEWPREFIX;
   MCW_idcode * idc ;
   THD_3dim_dataset * dset , * new_dset;
   double * avg = NULL;
   double * ca , * cb, * ra, * rb;
   MRI_IMAGE * card = NULL, * resp = NULL;
   MRI_IMAGE * cardphase = NULL, * respphase = NULL;
   float threshold = TRIC_C_DEF_THRESHOLD;
   int ignore = TRIC_I_DEF_IGNORE;
   int M = TRIC_M_DEF_ORDER;
   int winsize = TRIC_R_DEF_WINSIZE;
   float tr;
   int ival, nvals;
   FILE * fp;
   float * cpdata, * rpdata;
   int argi = 1;

   /*-------------------------------------------------------------*/
   /*----- Check arguments to see if they are reasonable-ish -----*/

   if (argc < 2 || strcmp(argv[1], "-help") == 0) {
       TRIC_printhelp();
       exit(-1);
   }

   mainENTRY("3dretroicor main"); PRINT_VERSION("3dretroicor") ;
   machdep();
   AFNI_logger("3dretroicor", argc, argv);

   /* Iterate over commandline args */
   while (argi < argc && argv[argi][0] == '-') {

       /*-- ignore --*/

       if (strcmp(argv[argi], "-ignore") == 0) {
	   if (argi + 1 >= argc) {
	       fprintf(stderr, "*** -ignore needs an argument!\n");
	       exit(1);
	   }
	   argi += 1;
	   ignore = atoi(argv[argi]);
	   if (ignore < 0) {
	       fprintf(stderr, "*** %i is not a valid number to ignore!\n",
		       ignore);
	       exit(1);
	   }
	   argi += 1;
	   continue;  /* Skip the rest of the loop and go to the next arg */
       }

       /*-- prefix --*/

       if (strcmp(argv[argi], "-prefix") == 0) {
	   if (argi + 1 >= argc) {
	       fprintf(stderr, "*** -prefix needs an argument!\n");
	       exit(1);
	   }
	   argi += 1;
	   MCW_strncpy(new_prefix, argv[argi], THD_MAX_PREFIX);
	   if (! THD_filename_ok(new_prefix)) {
	       fprintf(stderr, "*** %s is not a valid prefix!\n", new_prefix);
	       exit(1);
	   }
	   argi += 1;
	   continue;  /* Skip the rest of the loop and go to the next arg */
       }

       /*-- card --*/

       if (strcmp(argv[argi], "-card") == 0) {
	   if (argi + 1 >= argc) {
	       fprintf(stderr, "*** -card needs an argument!\n");
	       exit(1);
	   }
	   argi += 1;
	   card = mri_read_1D(argv[argi]);
	   if (card == NULL) {
	       fprintf(stderr, "*** Can't read -card %s\n", argv[argi]);
	       exit(1);
	   }
	   argi += 1;
	   continue;  /* Skip the rest of the loop and go to the next arg */
       }

       /*-- cardphase --*/

       if (strcmp(argv[argi], "-cardphase") == 0) {
	   if (argi + 1 >= argc) {
	       fprintf(stderr, "*** -cardphase needs an argument!\n");
	       exit(1);
	   }
	   argi += 1;
	   MCW_strncpy(cphase1d, argv[argi], 256);
	   if (! THD_filename_ok(cphase1d)) {
	       fprintf(stderr, "*** Bad name argument for -cardphase\n");
	       exit(1);
	   }
	   argi += 1;
	   continue;  /* Skip the rest of the loop and go to the next arg */
       }

       /*-- threshold --*/

       if (strcmp(argv[argi], "-threshold") == 0) {
	   if (argi + 1 >= argc) {
	       fprintf(stderr, "*** -threshold needs an argument!\n");
	       exit(1);
	   }
	   argi += 1;
	   threshold = atof(argv[argi]);
	   argi += 1;
	   continue;  /* Skip the rest of the loop and go to the next arg */
       }

       /*-- resp --*/

       if (strcmp(argv[argi], "-resp") == 0) {
	   if (argi + 1 >= argc) {
	       fprintf(stderr, "*** -resp needs an argument!\n");
	       exit(1);
	   }
	   argi += 1;
	   resp = mri_read_1D(argv[argi]);
	   if (resp == NULL) {
	       fprintf(stderr, "*** Can't read -resp %s\n", argv[argi]);
	       exit(1);
	   }
	   argi += 1;
	   continue;  /* Skip the rest of the loop and go to the next arg */
       }

       /*-- respphase --*/

       if (strcmp(argv[argi], "-respphase") == 0) {
	   if (argi + 1 >= argc) {
	       fprintf(stderr, "*** -respphase needs an argument!\n");
	       exit(1);
	   }
	   argi += 1;
	   MCW_strncpy(rphase1d, argv[argi], 256);
	   if (! THD_filename_ok(rphase1d)) {
	       fprintf(stderr, "*** Bad name argument for -respphase\n");
	       exit(1);
	   }
	   argi += 1;
	   continue;  /* Skip the rest of the loop and go to the next arg */
       }

       /*-- window --*/

       /*-- removed winsize ui --*/
#if 0
       if (strcmp(argv[argi], "-window") == 0) {
	   if (argi + 1 >= argc) {
	       fprintf(stderr, "*** -window needs an argument!\n");
	       exit(1);
	   }
	   argi += 1;
	   winsize = atoi(argv[argi]);
	   argi += 1;
	   continue;  /* Skip the rest of the loop and go to the next arg */
       }
#endif
       /*-- removed winsize ui --*/

       /*-- order --*/

       if (strcmp(argv[argi], "-order") == 0) {
	   if (argi + 1 >= argc) {
	       fprintf(stderr, "*** -order needs an argument!\n");
	       exit(1);
	   }
	   argi += 1;
	   M = atoi(argv[argi]);
	   if (M < 1) {
	       fprintf(stderr, "*** %i is not a valid order number\n", M);
	       exit(1);
	   }
	   argi += 1;
	   continue;  /* Skip the rest of the loop and go to the next arg */
       }
   } /* End iterating over commandline args */

   /* Check that at least one of Cardiac and Resp were selected */
   if (card == NULL && resp == NULL) {
       fprintf(stderr, "*** Need at least one correction (-card, -resp)\n");
       exit(1);
   }

   /*-- Open and check input dataset --*/

   if (argi >= argc) {
       fprintf(stderr, "*** No input dataset!?\n");
       exit(1);
   } else if (argi < argc - 1) {
       fprintf(stderr, "*** Too many input datasets?!\n");
       exit(1);
   }

   dset = THD_open_dataset(argv[argi]);
   if (! ISVALID_3DIM_DATASET(dset)) {
       fprintf(stderr, "*** Can't open dataset %s\n", argv[argi]);
       exit(1);
   }
   if (DSET_NUM_TIMES(dset) < 2) {
       fprintf(stderr, "*** Input dataset is not 3D+time!\n");
       exit(1);
   }

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

   /*-- copy the image data for editing in place --*/

   new_dset = EDIT_full_copy( dset , new_prefix );
   if( new_dset == NULL ) {
       fprintf(stderr, "*** Error copying dataset\n");
       exit(1);
   }
   tross_Copy_History(dset, new_dset); /* Copy and add to new_dset history */
   tross_Make_History("3dretroicor", argc, argv, new_dset);
   DSET_unload( dset ) ;  /* We won't need the old dataset anymore */

   /*-- calculate cardiac correction coefficients if requested --*/

   if (card != NULL) {
       /*-- convert cardiac waveform to phase --*/
       cardphase = RIC_ToCardiacPhase(card, threshold) ;
       if (cardphase == NULL) {
	   THD_delete_3dim_dataset( new_dset , False ) ;
	   fprintf(stderr, "*** Error transforming cardiac data\n");
	   exit(2);
       }

       /*-- calculate dataset voxel means --*/
       avg = RIC_CalcVoxelMeans(new_dset, ignore);
       if (avg == NULL) {
	   THD_delete_3dim_dataset( new_dset , False ) ;
	   mri_free(cardphase);
	   fprintf(stderr, "*** Error calculating dataset voxel means\n");
	   exit(2);
       }

       /*-- calculate coefficients for each voxel --*/
       if (RIC_CalcCoeffAB(new_dset, cardphase, avg, &ca, &cb, M, ignore)
	   != 0) {

	   THD_delete_3dim_dataset( new_dset , False ) ;
	   mri_free(cardphase);
	   fprintf(stderr, "*** Error calculating cardiac a b coefficients\n");
	   exit(2);
       }
   }

   /*-- calculate respiratory correction coefficients if requested --*/

   if (resp != NULL) {
       /*-- Set winsize to 1/2 sampling rate of resp in Hz --*/
       tr = new_dset->taxis->ttdel;
       switch (new_dset->taxis->units_type) {
       case UNITS_MSEC_TYPE: tr /= 1000; break;
       case UNITS_SEC_TYPE:  break;
       case UNITS_HZ_TYPE:   tr = 1 / tr; break;
       default:
	   THD_delete_3dim_dataset( new_dset , False ) ;
	   fprintf(stderr, "*** Bad time units type in dataset\n");
	   exit(2);
       }
       winsize = ceil(resp->nx / (tr * DSET_NVALS(new_dset)) / 2.0);

       /*-- convert respiratory waveform to phase --*/
       respphase = RIC_ToRespPhase(resp, winsize) ;
       if (respphase == NULL) {
	   THD_delete_3dim_dataset( new_dset , False ) ;
	   fprintf(stderr, "*** Error transforming resp data\n");
	   exit(2);
       }

       /*-- calculate dataset voxel means if not already done --*/
       if (avg == NULL) {
	   avg = RIC_CalcVoxelMeans(new_dset, ignore);
	   if (avg == NULL) {
	       THD_delete_3dim_dataset( new_dset , False ) ;
	       mri_free(respphase);
	       fprintf(stderr, "*** Error calculating dataset voxel means2\n");
	       exit(2);
	   }
       }

       /*-- calculate coefficients for each voxel --*/
       if (RIC_CalcCoeffAB(new_dset, respphase, avg, &ra, &rb, M, ignore)
	   != 0) {

	   THD_delete_3dim_dataset( new_dset , False ) ;
	   mri_free(respphase);
	   fprintf(stderr, "*** Error calculating resp a, b coefficients\n");
	   exit(2);
       }
   }

   /*-- do cardiac correction if requested --*/

   if (card != NULL) {
       /*-- correct the image data --*/
       if (RIC_CorrectDataset(new_dset, cardphase, ca, cb, M, ignore) != 0) {
	   THD_delete_3dim_dataset( new_dset , False ) ;
	   mri_free(cardphase);
	   free(ca); free(cb);
	   fprintf(stderr, "*** Error applying cardiac correction\n");
	   exit(3);
       }

       /*-- if requested, write phase data to file and pass to AFNI --*/
       if ( THD_filename_ok(cphase1d) ) {
	   /* Write the file */
	   fp = fopen(cphase1d, "w");
	   nvals = cardphase->nx;
	   cpdata = MRI_FLOAT_PTR(cardphase);
	   for (ival = 0; ival < nvals; ival += 1) {
	       fprintf(fp, "%f\n", cpdata[ival]);
	   }
	   fclose(fp);
       }

       mri_free(cardphase);
       free(ca); free(cb); free(avg); avg = NULL;
   }

   /*-- do resp correction if requested --*/

   if (resp != NULL) {
       /*-- correct the image data --*/
       if (RIC_CorrectDataset(new_dset, respphase, ra, rb, M, ignore) != 0) {
	   THD_delete_3dim_dataset( new_dset , False ) ;
	   mri_free(respphase);
	   free(ra); free(rb);
	   fprintf(stderr, "*** Error applying resp correction\n");
	   exit(3);
       }

       /*-- if requested, write phase data to file and pass to AFNI --*/
       if ( THD_filename_ok(rphase1d) ) {
	   /* Write the file */
	   fp = fopen(rphase1d, "w");
	   nvals = respphase->nx;
	   rpdata = MRI_FLOAT_PTR(respphase);
	   for (ival = 0; ival < nvals; ival += 1) {
	       fprintf(fp, "%f\n", rpdata[ival]);
	   }
	   fclose(fp);
       }

       mri_free(respphase);
       free(ra); free(rb); if (avg != NULL) free(avg);
   }

   /*-- write out new dataset --*/

   if (DSET_write(new_dset) != False) {
      fprintf(stderr,"++ output dataset: %s\n",DSET_BRIKNAME(new_dset)) ;
      exit(0) ;
   } else {
      fprintf(stderr,
         "** 3dretroicor: Failed to write output!\n" ) ;
      exit(1) ;
   }

   /*-- done successfully!!! --*/

   exit(0);
}
Exemplo n.º 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) ;
   }
   
}
Exemplo n.º 30
0
int main( int argc , char *argv[] )
{
   int iarg , nerr=0 , nvals,nvox , nx,ny,nz , ii,jj,kk ;
   char *prefix="LSSout" , *save1D=NULL , nbuf[256] ;
   THD_3dim_dataset *inset=NULL , *outset ;
   MRI_vectim   *inset_mrv=NULL ;
   byte *mask=NULL ; int mask_nx=0,mask_ny=0,mask_nz=0, automask=0, nmask=0 ;
   NI_element *nelmat=NULL ; char *matname=NULL ;
   char *cgl ;
   int Ngoodlist,*goodlist=NULL , nfull , ncmat,ntime ;
   NI_int_array *giar ; NI_str_array *gsar ; NI_float_array *gfar ;
   MRI_IMAGE *imX, *imA, *imC, *imS ; float *Xar, *Sar ; MRI_IMARR *imar ;
   int nS ; float *ss , *oo , *fv , sum ; int nvec , iv ;
   int nbstim , nst=0 , jst_bot,jst_top ; char *stlab="LSS" ;
   int nodata=1 ;

   /*--- help me if you can ---*/

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

   /*--- bureaucratic startup ---*/

   PRINT_VERSION("3dLSS"); mainENTRY("3dLSS main"); machdep();
   AFNI_logger("3dLSS",argc,argv); AUTHOR("RWCox");
   (void)COX_clock_time() ;

   /**------- scan command line --------**/

   iarg = 1 ;
   while( iarg < argc ){

     if( strcmp(argv[iarg],"-verb") == 0 ){ verb++  ; iarg++ ; continue ; }
     if( strcmp(argv[iarg],"-VERB") == 0 ){ verb+=2 ; iarg++ ; continue ; }

     /**==========   -mask  ==========**/

     if( strcasecmp(argv[iarg],"-mask") == 0 ){
       THD_3dim_dataset *mset ;
       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 '%.33s'",argv[iarg]) ;
       nmask = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ;
       if( verb || nmask < 1 ) INFO_message("Number of voxels in mask = %d",nmask) ;
       if( nmask < 1 ) ERROR_exit("Mask is too small to process") ;
       iarg++ ; continue ;
     }

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

     /**==========   -matrix  ==========**/

     if( strcasecmp(argv[iarg],"-matrix") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ;
       if( nelmat != NULL ) ERROR_exit("More than 1 -matrix option!?");
       nelmat = NI_read_element_fromfile( argv[iarg] ) ; /* read NIML file */
       matname = argv[iarg];
       if( nelmat == NULL || nelmat->type != NI_ELEMENT_TYPE )
         ERROR_exit("Can't process -matrix file '%s'!?",matname) ;
       iarg++ ; continue ;
     }

     /**==========   -nodata  ===========**/

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

     /**==========   -input  ==========**/

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

     /**==========   -prefix  =========**/

     if( strcasecmp(argv[iarg],"-prefix") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ;
       prefix = strdup(argv[iarg]) ;
       if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal string after %s",argv[iarg-1]) ;
       if( verb && strcmp(prefix,"NULL") == 0 )
         INFO_message("-prefix NULL ==> no dataset will be written") ;
       iarg++ ; continue ;
     }

     /**==========   -save1D  =========**/

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

     /***** Loser User *****/

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

   }  /* end of loop over options */

   /*----- check for errors -----*/

   if( nelmat == NULL ){ ERROR_message("No -matrix option!?") ; nerr++ ; }
   if( nerr > 0 ) ERROR_exit("Can't continue without these inputs!") ;

   if( inset != NULL ){
     nvals = DSET_NVALS(inset) ; nvox = DSET_NVOX(inset) ;
     nx = DSET_NX(inset) ; ny = DSET_NY(inset) ; nz = DSET_NZ(inset) ;
   } else {
     automask = nvals = 0 ;
     nvox = nx = ny = nz = nodata = 1 ;  /* nodata */
     mask = NULL ;
   }

   /*----- masque -----*/

   if( mask != NULL ){     /* check -mask option for compatibility */
     if( mask_nx != nx || mask_ny != ny || mask_nz != nz )
       ERROR_exit("-mask dataset grid doesn't match input dataset :-(") ;

   } else if( automask ){  /* create a mask from input dataset */
     mask = THD_automask( inset ) ;
     if( mask == NULL )
       ERROR_message("Can't create -automask from input dataset :-(") ;
     nmask = THD_countmask( nvox , mask ) ;
     if( verb || nmask < 1 )
       INFO_message("Number of voxels in automask = %d (out of %d = %.1f%%)",
                    nmask, nvox, (100.0f*nmask)/nvox ) ;
     if( nmask < 1 ) ERROR_exit("Automask is too small to process") ;

   } else if( !nodata ) {       /* create a 'mask' for all voxels */
     if( verb )
       INFO_message("No mask ==> computing for all %d voxels",nvox) ;
     mask = (byte *)malloc(sizeof(byte)*nvox) ; nmask = nvox ;
     memset( mask , 1 , sizeof(byte)*nvox ) ;

   }

   /*----- get matrix info from the NIML element -----*/

   if( verb ) INFO_message("extracting matrix info") ;

   ncmat = nelmat->vec_num ;  /* number of columns */
   ntime = nelmat->vec_len ;  /* number of rows */
   if( ntime < ncmat+2 )
     ERROR_exit("Matrix has too many columns (%d) for number of rows (%d)",ncmat,ntime) ;

   /*--- number of rows in the full matrix (without censoring) ---*/

   cgl = NI_get_attribute( nelmat , "NRowFull" ) ;
   if( cgl == NULL ) ERROR_exit("Matrix is missing 'NRowFull' attribute!") ;
   nfull = (int)strtod(cgl,NULL) ;
   if( nodata ){
     nvals = nfull ;
   } else if( nvals != nfull ){
     ERROR_exit("-input dataset has %d time points, but matrix indicates %d",
                nvals , nfull ) ;
   }

   /*--- the goodlist = mapping from matrix row index to time index
                        (which allows for possible time point censoring) ---*/

   cgl = NI_get_attribute( nelmat , "GoodList" ) ;
   if( cgl == NULL ) ERROR_exit("Matrix is missing 'GoodList' attribute!") ;
   giar = NI_decode_int_list( cgl , ";," ) ;
   if( giar == NULL || giar->num < ntime )
     ERROR_exit("Matrix 'GoodList' badly formatted?!") ;
   Ngoodlist = giar->num ; goodlist = giar->ar ;
   if( Ngoodlist != ntime )
     ERROR_exit("Matrix 'GoodList' incorrect length?!") ;
   else if( verb > 1 && Ngoodlist < nfull )
     ININFO_message("censoring reduces time series length from %d to %d",nfull,Ngoodlist) ;

   /*--- extract the matrix from the NIML element ---*/

   imX = mri_new( ntime , ncmat , MRI_float ) ;
   Xar = MRI_FLOAT_PTR(imX) ;

   if( nelmat->vec_typ[0] == NI_FLOAT ){  /* from 3dDeconvolve_f */
     float *cd ;
     for( jj=0 ; jj < ncmat ; jj++ ){
       cd = (float *)nelmat->vec[jj] ;
       for( ii=0 ; ii < ntime ; ii++ ) Xar[ii+jj*ntime] = cd[ii] ;
     }
   } else if( nelmat->vec_typ[0] == NI_DOUBLE ){  /* from 3dDeconvolve */
     double *cd ;
     for( jj=0 ; jj < ncmat ; jj++ ){
       cd = (double *)nelmat->vec[jj] ;
       for( ii=0 ; ii < ntime ; ii++ ) Xar[ii+jj*ntime] = cd[ii] ;
     }
   } else {
     ERROR_exit("Matrix file stored with illegal data type!?") ;
   }

   /*--- find the stim_times_IM option ---*/

   cgl = NI_get_attribute( nelmat , "BasisNstim") ;
   if( cgl == NULL ) ERROR_exit("Matrix doesn't have 'BasisNstim' attribute!") ;
   nbstim = (int)strtod(cgl,NULL) ;
   if( nbstim <= 0 ) ERROR_exit("Matrix 'BasisNstim' attribute is %d",nbstim) ;
   for( jj=1 ; jj <= nbstim ; jj++ ){
     sprintf(nbuf,"BasisOption_%06d",jj) ;
     cgl = NI_get_attribute( nelmat , nbuf ) ;
     if( cgl == NULL || strcmp(cgl,"-stim_times_IM") != 0 ) continue ;
     if( nst > 0 )
       ERROR_exit("More than one -stim_times_IM option was found in the matrix") ;
     nst = jj ;
     sprintf(nbuf,"BasisColumns_%06d",jj) ;
     cgl = NI_get_attribute( nelmat , nbuf ) ;
     if( cgl == NULL )
       ERROR_exit("Matrix doesn't have %s attribute!",nbuf) ;
     jst_bot = jst_top = -1 ;
     sscanf(cgl,"%d:%d",&jst_bot,&jst_top) ;
     if( jst_bot < 0 || jst_top < 0 )
       ERROR_exit("Can't decode matrix attribute %s",nbuf) ;
     if( jst_bot == jst_top )
       ERROR_exit("Matrix attribute %s shows only 1 column for -stim_time_IM:\n"
                  "      -->> 3dLSS is meant to be used when more than one stimulus\n"
                  "           time was given, and then it computes the response beta\n"
                  "           for each stim time separately. If you have only one\n"
                  "           stim time with -stim_times_IM, you can use the output\n"
                  "           dataset from 3dDeconvolve (or 3dREMLfit) to get that\n"
                  "           single beta directly.\n" , nbuf ) ;
     if( jst_bot >= jst_top || jst_top >= ncmat )
       ERROR_exit("Matrix attribute %s has illegal value: %d:%d (ncmat=%d)",nbuf,jst_bot,jst_top,ncmat) ;
     sprintf(nbuf,"BasisName_%06d",jj) ;
     cgl = NI_get_attribute( nelmat , nbuf ) ;
     if( cgl != NULL ) stlab = strdup(cgl) ;
     if( verb > 1 )
       ININFO_message("-stim_times_IM at stim #%d; cols %d..%d",jj,jst_bot,jst_top) ;
   }
   if( nst == 0 )
     ERROR_exit("Matrix doesn't have any -stim_times_IM options inside :-(") ;

   /*--- mangle matrix to segregate IM regressors from the rest ---*/

   if( verb ) INFO_message("setting up LSS vectors") ;

   imar = LSS_mangle_matrix( imX , jst_bot , jst_top ) ;
   if( imar == NULL )
     ERROR_exit("Can't compute LSS 'mangled' matrix :-(") ;

   /*--- setup for LSS computations ---*/

   imA = IMARR_SUBIM(imar,0) ;
   imC = IMARR_SUBIM(imar,1) ;
   imS = LSS_setup( imA , imC ) ; DESTROY_IMARR(imar) ;
   if( imS == NULL )
     ERROR_exit("Can't complete LSS setup :-((") ;
   nS = imS->ny ; Sar = MRI_FLOAT_PTR(imS) ;

   if( save1D != NULL ){
     mri_write_1D( save1D , imS ) ;
     if( verb ) ININFO_message("saved LSS vectors into file %s",save1D) ;
   } else if( nodata ){
     WARNING_message("-nodata used but -save1D not used ==> you get no output!") ;
   }

   if( nodata || strcmp(prefix,"NULL") == 0 ){
     INFO_message("3dLSS ends since prefix is 'NULL' or -nodata was used") ;
     exit(0) ;
   }

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

   if( verb ) INFO_message("creating output datset in memory") ;

   outset = EDIT_empty_copy(inset) ;
   EDIT_dset_items( outset ,
                      ADN_prefix    , prefix    ,
                      ADN_datum_all , MRI_float ,
                      ADN_brick_fac , NULL      ,
                      ADN_nvals     , nS        ,
                      ADN_ntt       , nS        ,
                    ADN_none ) ;
   tross_Copy_History( inset , outset ) ;
   tross_Make_History( "3dLSS" , argc,argv , outset ) ;
   for( kk=0 ; kk < nS ; kk++ ){
     EDIT_substitute_brick( outset , kk , MRI_float , NULL ) ;
     sprintf(nbuf,"%s#%03d",stlab,kk) ;
     EDIT_BRICK_LABEL( outset , kk , nbuf ) ;
   }

   /*----- convert input dataset to vectim -----*/

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

   DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ;
   inset_mrv = THD_dset_to_vectim( inset , mask , 0 ) ;
   DSET_unload(inset) ;

   /*----- compute dot products, store results -----*/

   if( verb ) INFO_message("computing away, me buckos!") ;

   nvec = inset_mrv->nvec ;
   for( kk=0 ; kk < nS ; kk++ ){
     ss = Sar + kk*ntime ;
     oo = DSET_ARRAY(outset,kk) ;
     for( iv=0 ; iv < nvec ; iv++ ){
       fv = VECTIM_PTR(inset_mrv,iv) ;
       for( sum=0.0f,ii=0 ; ii < ntime ; ii++ )
         sum += ss[ii] * fv[goodlist[ii]] ;
       oo[inset_mrv->ivec[iv]] = sum ;
     }
   }

   DSET_write(outset) ; WROTE_DSET(outset) ;

   /*-------- Hasta la vista, baby --------*/

   if( verb )
     INFO_message("3dLSS finished: total CPU=%.2f Elapsed=%.2f",
                  COX_cpu_time() , COX_clock_time() ) ;
   exit(0) ;
}