Esempio n. 1
0
/*-------------------------------------------------------*/
MRI_IMARR * dset_to_mri(THD_3dim_dataset * dset)
/*--------------------------------------------------------*/
{

   int ii, kk, ntime, datum;
   int nvox, nx, ny, nz;
   int use_fac;
   
   MRI_IMARR * ims_in;
   MRI_IMAGE * im, *temp_im;
   

   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 * fac  = NULL ;  /* array of brick scaling factors */
   
   float * fout;
   

   ntime = DSET_NUM_TIMES(dset) ;
   nx = dset->daxes->nxx;
   ny = dset->daxes->nyy;
   nz = dset->daxes->nzz;
   nvox = dset->daxes->nxx * dset->daxes->nyy * dset->daxes->nzz ;
   datum = DSET_BRICK_TYPE( dset , 0 ) ; /* get dataset datum type */

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

      default:
         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..ntime-1.  */

      case MRI_byte:
         bptr = (byte **) malloc( sizeof(byte *) * ntime ) ;
         if( bptr == NULL ) return NULL ;
         for( kk=0 ; kk < ntime ; kk++ )
            bptr[kk] = (byte *) DSET_ARRAY(dset,kk) ;
      break ;

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

      case MRI_short:
         sptr = (short **) malloc( sizeof(short *) * ntime ) ;
         if( sptr == NULL ) return NULL ;
         for( kk=0 ; kk < ntime; kk++ )
            sptr[kk] = (short *) DSET_ARRAY(dset,kk) ;
      break ;

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

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

   } /* end of switch on input type */
   
   INIT_IMARR(ims_in) ;
   for( kk=0 ; kk < ntime ; kk++ ){
      im = mri_new_vol_empty( nx , ny , nz , datum ) ;
      ADDTO_IMARR(ims_in,im) ;
   }
   
   for( kk=0 ; kk < ntime ; kk++ ){
      im = IMARR_SUBIMAGE(ims_in,kk) ;
      
      switch( datum ){
         case MRI_byte:  mri_fix_data_pointer( bptr[kk], im ) ; break ;
         case MRI_short: mri_fix_data_pointer( sptr[kk], im ) ; break ;
         case MRI_float: mri_fix_data_pointer( fptr[kk], im ) ; break ;
      }
   }


   
   return(ims_in);
}
Esempio n. 2
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) ;
}
Esempio n. 3
0
int main( int argc , char * argv[] )
{
   char prefix[255]="obi-wan-kenobi" , fname[255] ;
   int datum = -1 ;
   int iarg = 1 ;
   int gnim , nx , ny , nz , kz ;
   char ** gname ;
   MRI_IMARR * arr ;
   MRI_IMAGE * im , * qim ;
   FILE * fp ;

   /***** help? *****/

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
      printf(
       "Usage: imstack [options] image_filenames ...\n"
       "Stacks up a set of 2D images into one big file (a la MGH).\n"
       "Options:\n"
       "  -datum type   Converts the output data file to be 'type',\n"
       "                  which is either 'short' or 'float'.\n"
       "                  The default type is the type of the first image.\n"
       "  -prefix name  Names the output files to be 'name'.b'type' and 'name'.hdr.\n"
       "                  The default name is 'obi-wan-kenobi'.\n"
      ) ;

      exit(0) ;
   }

   machdep() ;

   /***** scan for option *****/

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

      /*** -datum ***/

      if( strcmp(argv[iarg],"-datum") == 0 ){
         if( ++iarg >= argc ){
            fprintf(stderr,"-datum needs a type!\n") ; exit(1) ;
         }
         if( strcmp(argv[iarg],"short") == 0 ){
            datum = MRI_short ;
         } else if( strcmp(argv[iarg],"float") == 0 ){
            datum = MRI_float ;
         } else {
            fprintf(stderr,"-datum %s is illegal!\n",argv[iarg]) ; exit(1) ;
         }
         iarg++ ; continue ;
      }

      /*** -prefix ***/

      if( strcmp(argv[iarg],"-prefix") == 0 ){
         if( ++iarg >= argc ){
            fprintf(stderr,"-prefix needs a name!\n") ; exit(1) ;
         }
         strcpy(prefix,argv[iarg]) ;
         iarg++ ; continue ;
      }

      /*** ERROR ***/

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

   /***** Check if any filenames left *****/

   if( iarg >= argc ){
      fprintf(stderr,"No input image filenames?!\n") ; exit(1) ;
   }

   /***** Perform filename expansion on the input list *****/

   MCW_warn_expand(1) ;
   MCW_file_expand( argc - iarg , argv + iarg , &gnim , &gname ) ;
   MCW_warn_expand(0) ;

   if( gnim < 1 ){
      fprintf(stderr,"Filename expansion fails on input filenames?!\n") ; exit(1) ;
   }

   /***** Read all files *****/

   arr = mri_read_many_files( gnim , gname ) ;
   if( arr == NULL || IMARR_COUNT(arr) <= 0 ){
      fprintf(stderr,"Can't read input files?!\n") ; exit(1) ;
   }
   MCW_free_expand( gnim , gname ) ;
   fprintf(stderr,"Read in %d 2D slices\n",IMARR_COUNT(arr)) ;

   /***** Set output datum, if not already fixed *****/

   if( datum < 0 ){
      datum = IMARR_SUBIMAGE(arr,0)->kind ;

      if( datum != MRI_short && datum != MRI_float ){
         fprintf(stderr,"Input image type is %s -- you must use -datum!\n",
                 MRI_TYPE_name[datum]) ;
         exit(1) ;
      }
   }

   /***** Check images for equal sizes *****/

   nx = IMARR_SUBIMAGE(arr,0)->nx ;
   ny = IMARR_SUBIMAGE(arr,0)->ny ;
   nz = IMARR_COUNT(arr) ;

   for( kz=1 ; kz < nz ; kz++ ){
      if( IMARR_SUBIMAGE(arr,kz)->nx != nx ||
          IMARR_SUBIMAGE(arr,kz)->ny != ny   ){

         fprintf(stderr,"All images must be the same size (%d x %d)\n",nx,ny) ;
         exit(1) ;
      }
   }

   /***** Write the output brick *****/

   sprintf(fname,"%s.b%s",prefix,MRI_TYPE_name[datum]) ;
   fp = fopen( fname , "w" ) ;
   if( fp == NULL ){
      fprintf(stderr,"Can't open output file %s\n",fname) ; exit(1) ;
   }

   for( kz=0 ; kz < nz ; kz++ ){

      im = IMARR_SUBIMAGE(arr,kz) ;
      if( im->kind != datum ) qim = mri_to_mri( datum , im ) ;
      else                    qim = im ;

      fwrite( mri_data_pointer(qim) , qim->pixel_size , qim->nx * qim->ny , fp ) ;

      if( qim != im ) mri_free(qim) ;
      mri_free(im);
   }
   fclose( fp ) ;
   fprintf(stderr,"Wrote output brick %s\n",fname) ;

   /***** Write the output header *****/

   sprintf(fname,"%s.hdr",prefix) ;
   fp = fopen( fname , "w" ) ;
   if( fp == NULL ){
      fprintf(stderr,"Can't open output file %s\n",fname) ; exit(1) ;
   }

   fprintf( fp , "%d %d %d 0\n" , nx,ny,nz ) ;
   fclose(fp) ;
   fprintf(stderr,"Wrote output header %s: %d %d %d\n",fname,nx,ny,nz) ;

   exit(0) ;
}
Esempio n. 4
0
MRI_IMAGE * mri_cat2D(  int mx , int my , int gap , 
                        void *gapval , MRI_IMARR *imar )
{
   int nx , ny , ii , jj , kind , ij , nxout , nyout , ijoff , jout,iout ;
   MRI_IMAGE *imout , *imin=NULL ;
   void *vout ;

ENTRY("mri_cat2D") ;

   /*--- sanity checks ---*/

   if(   mx < 1 || my < 1 || imar == NULL || 
         (!OK_wrap && imar->num < mx*my) ) 
      RETURN( NULL );   
   if( gap < 0 || (gap > 0 && gapval == NULL) )                RETURN( NULL );

   for( ij=0 ; ij < mx*my ; ij++ ){     /* find first non-empty image */
      imin = IMARR_SUBIMAGE(imar,ij%imar->num) ;
      if( imin != NULL ) break ;
   }
   if( ij == mx*my ) RETURN( NULL );      /* all are empty! */

   kind = imin->kind ;
   nx   = imin->nx ;
   ny   = imin->ny ;


   if( mx==1 && my==1 ){                    /* 1x1 case (shouldn't happen) */
      imout = mri_to_mri( kind , imin ) ;   /* Just copy input to output   */
      RETURN( imout );
   }


   for( ij=0 ; ij < mx*my ; ij++ ){     /* check for consistency */
      imin = IMARR_SUBIMAGE(imar,ij%imar->num) ;
      if( imin != NULL &&
          (imin->kind != kind || imin->nx != nx || imin->ny != ny) )
         RETURN( NULL );
   }

   nxout = mx * nx + (mx-1) * gap ;
   nyout = my * ny + (my-1) * gap ;
   imout = mri_new( nxout , nyout , kind ) ;
   vout  = mri_data_pointer( imout ) ;


   ij = 0 ;
   for( jj=0 ; jj < my ; jj++ ){            /* loop over rows */
      for( ii=0 ; ii < mx ; ii++ , ij++ ){  /* loop over columns */

         if (WrapZero && ij >= imar->num) imin = NULL;
         else imin  = IMARR_SUBIMAGE(imar,ij%imar->num) ;
         ijoff = ii * (nx+gap) + jj * (ny+gap) * nxout ;

         /*--- NULL image ==> fill this spot with zeroes ---*/

         if( imin == NULL || mri_data_pointer(imin) == NULL ){
            switch( kind ){
               case MRI_byte:{
                  byte *pout = ((byte *) vout);
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     (void) memset( pout+ijoff , 0 , sizeof(byte)*nx ) ;
               } break ;

               case MRI_rgb:{                       /* 11 Feb 1999 */
                  byte *pout = ((byte *) vout);
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     (void) memset( pout+(3*ijoff) , 0 , sizeof(byte)*(3*nx) ) ;
               } break ;

               case MRI_short:{
                  short *pout = ((short *) vout);
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     (void) memset( pout+ijoff , 0 , sizeof(short)*nx ) ;
               } break ;

               case MRI_int:{
                  int *pout = ((int *) vout);
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     (void) memset( pout+ijoff , 0 , sizeof(int)*nx ) ;
               } break ;

               case MRI_float:{
                  float *pout = ((float *) vout);
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     for( iout=0 ; iout < nx ; iout++ )
                        pout[iout+ijoff] = 0 ;
               } break ;

               case MRI_double:{
                  double *pout = ((double *) vout);
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     for( iout=0 ; iout < nx ; iout++ )
                        pout[iout+ijoff] = 0 ;
               } break ;

               case MRI_complex:{
                  complex *pout = ((complex *) vout);
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     for( iout=0 ; iout < nx ; iout++ )
                        pout[iout+ijoff].r = pout[iout+ijoff].i = 0 ;
               } break ;
            }

         /*--- Copy input image data into place ---*/

         } else {
            switch( kind ){
               case MRI_byte:{
                  byte *pout = ((byte *) vout) ,
                       *pin  =  (byte *) MRI_BYTE_PTR(imin) ;
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     memcpy( pout+ijoff , pin , sizeof(byte)*nx ) , pin += nx ;
               } break ;

               case MRI_rgb:{                               /* 11 Feb 1999 */
                  byte *pout = ((byte *) vout) ,
                       *pin  =  (byte *) MRI_RGB_PTR(imin) ;
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     memcpy( pout+(3*ijoff) , pin , sizeof(byte)*(3*nx) ) , pin += 3*nx ;
               } break ;

               case MRI_short:{
                  short *pout = ((short *) vout) ,
                        *pin  =  (short *) MRI_SHORT_PTR(imin) ;
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     memcpy( pout+ijoff , pin , sizeof(short)*nx ) , pin += nx ;
               } break ;

               case MRI_int:{
                  int *pout = ((int *) vout) ,
                      *pin  =  (int *) MRI_INT_PTR(imin) ;
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     memcpy( pout+ijoff , pin , sizeof(int)*nx ) , pin += nx ;
               } break ;

               case MRI_float:{
                  float *pout = ((float *) vout) ,
                        *pin  =  (float *) MRI_FLOAT_PTR(imin) ;
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     memcpy( pout+ijoff , pin , sizeof(float)*nx ) , pin += nx ;
               } break ;

               case MRI_double:{
                  double *pout = ((double *) vout) ,
                         *pin  =  (double *) MRI_DOUBLE_PTR(imin) ;
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     memcpy( pout+ijoff , pin , sizeof(double)*nx ) , pin += nx ;
               } break ;

               case MRI_complex:{
                  complex *pout = ((complex *) vout) ,
                          *pin  =  (complex *) MRI_COMPLEX_PTR(imin) ;
                  for( jout=0 ; jout < ny ; jout++ , ijoff+=nxout )
                     memcpy( pout+ijoff , pin , sizeof(complex)*nx ) , pin += nx ;
               } break ;
            }
         }
      }
   }

   /*******************  Deal with the gaps  *******************/

   if( gap > 0 ){

      /**** put value into gap after each row ****/

      ii = nxout * gap ;
      for( jj=0 ; jj < my-1 ; jj++ ){
         ijoff = (ny + jj * (ny+gap)) * nxout ;
         switch( kind ){
            case MRI_byte:{
               byte gval = *((byte *)gapval) , *pout = ((byte *) vout) ;
               for( ij=0 ; ij < ii ; ij++ ) pout[ij+ijoff] = gval ;
            } break ;

            case MRI_rgb:{       /* 11 Feb 1999 */
               byte rval = *(((byte *)gapval)  ) ,
                    gval = *(((byte *)gapval)+1) ,
                    bval = *(((byte *)gapval)+2) , *pout = ((byte *) vout) ;

               for( ij=0 ; ij < ii ; ij++ ){
                  pout[3*(ij+ijoff)  ] = rval ;
                  pout[3*(ij+ijoff)+1] = gval ;
                  pout[3*(ij+ijoff)+2] = bval ;
               }
            } break ;

            case MRI_short:{
               short gval = *((short *)gapval) , *pout = ((short *) vout) ;
               for( ij=0 ; ij < ii ; ij++ ) pout[ij+ijoff] = gval ;
            } break ;

            case MRI_float:{
               float gval = *((float *)gapval) , *pout = ((float *) vout) ;
               for( ij=0 ; ij < ii ; ij++ ) pout[ij+ijoff] = gval ;
            } break ;

            case MRI_int:{
               int gval = *((int *)gapval) , *pout = ((int *) vout) ;
               for( ij=0 ; ij < ii ; ij++ ) pout[ij+ijoff] = gval ;
            } break ;

            case MRI_double:{
               double gval = *((double *)gapval) , *pout = ((double *) vout) ;
               for( ij=0 ; ij < ii ; ij++ ) pout[ij+ijoff] = gval ;
            } break ;

            case MRI_complex:{
               complex gval = *((complex *)gapval) , *pout = ((complex *) vout) ;
               for( ij=0 ; ij < ii ; ij++ ) pout[ij+ijoff] = gval ;
            } break ;
         }
      }

      /**** put value into gap after each column ****/

      for( ii=0 ; ii < mx-1 ; ii++ ){
         ijoff = nx + ii*(nx+gap) ;
         switch( kind ){
            case MRI_byte:{
               byte gval = *((byte *)gapval) , *pout = ((byte *) vout) ;
               for( ij=0 ; ij < gap ; ij++ , ijoff++ )
                  for( jj=0 ; jj < nyout ; jj++ ) pout[jj*nxout+ijoff] = gval ;
            } break ;

            case MRI_rgb:{              /* 11 Feb 1999 */
               byte rval = *(((byte *)gapval)  ) ,
                    gval = *(((byte *)gapval)+1) ,
                    bval = *(((byte *)gapval)+2) , *pout = ((byte *) vout) ;

               for( ij=0 ; ij < gap ; ij++ , ijoff++ )
                  for( jj=0 ; jj < nyout ; jj++ ){
                     pout[3*(jj*nxout+ijoff)  ] = rval ;
                     pout[3*(jj*nxout+ijoff)+1] = gval ;
                     pout[3*(jj*nxout+ijoff)+2] = bval ;
                  }
            } break ;

            case MRI_short:{
               short gval = *((short *)gapval) , *pout = ((short *) vout) ;
               for( ij=0 ; ij < gap ; ij++ , ijoff++ )
                  for( jj=0 ; jj < nyout ; jj++ ) pout[jj*nxout+ijoff] = gval ;
            } break ;

            case MRI_float:{
               float gval = *((float *)gapval) , *pout = ((float *) vout) ;
               for( ij=0 ; ij < gap ; ij++ , ijoff++ )
                  for( jj=0 ; jj < nyout ; jj++ ) pout[jj*nxout+ijoff] = gval ;
            } break ;

            case MRI_int:{
               int gval = *((int *)gapval) , *pout = ((int *) vout) ;
               for( ij=0 ; ij < gap ; ij++ , ijoff++ )
                  for( jj=0 ; jj < nyout ; jj++ ) pout[jj*nxout+ijoff] = gval ;
            } break ;

            case MRI_double:{
               double gval = *((double *)gapval) , *pout = ((double *) vout) ;
               for( ij=0 ; ij < gap ; ij++ , ijoff++ )
                  for( jj=0 ; jj < nyout ; jj++ ) pout[jj*nxout+ijoff] = gval ;
            } break ;

            case MRI_complex:{
               complex gval = *((complex *)gapval) , *pout = ((complex *) vout) ;
               for( ij=0 ; ij < gap ; ij++ , ijoff++ )
                  for( jj=0 ; jj < nyout ; jj++ ) pout[jj*nxout+ijoff] = gval ;
            } break ;
         }
      }
   }

   RETURN( imout );
}
Esempio n. 5
0
void DT_read_opts( int argc , char * argv[] )
{
   int nopt = 1 , nvals , ii , nvcheck , nerr=0 ;
   MRI_IMARR *slice_imar ;

   INIT_IMARR(DT_imar) ;
   INIT_IMARR(slice_imar) ;

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

      /**** -polort p ****/

      if( strncmp(argv[nopt],"-polort",6) == 0 ){
        char *cpt ;
        nopt++ ;
        if( nopt >= argc ) ERROR_exit("Need argument after -polort") ;
        DT_polort = (int)strtod(argv[nopt],&cpt) ;
        if( *cpt != '\0' ) WARNING_message("Illegal non-numeric value after -polort") ;
        if( DT_polort < 0 )
          WARNING_message("Ignoring negative value after -polort") ;
        nopt++ ; continue ;
      }

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

      if( strncmp(argv[nopt],"-prefix",6) == 0 ){
        nopt++ ;
        if( nopt >= argc ) ERROR_exit("Need argument after -prefix") ;
        MCW_strncpy( DT_output_prefix , argv[nopt] , THD_MAX_PREFIX ) ;
        if( !THD_filename_ok(DT_output_prefix) )
          ERROR_exit("bad name '%s' after -prefix",argv[nopt]) ;
        nopt++ ; continue ;
      }

      /**** -session directory ****/

      if( strncmp(argv[nopt],"-session",6) == 0 ){
        nopt++ ;
        if( nopt >= argc ) ERROR_exit("Need argument after -session") ;
        MCW_strncpy( DT_session , argv[nopt] , THD_MAX_NAME ) ;
        if( !THD_filename_ok(DT_session) )
          ERROR_exit("bad name '%s' after -session",argv[nopt]) ;
        nopt++ ; continue ;
      }

      /**** -verb ****/

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

      /**** -replace ****/

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

      /**** -byslice [08 Dec 1999] ****/

      if( strncmp(argv[nopt],"-byslice",5) == 0 ){
#ifdef ALLOW_BYSLICE
        if( IMARR_COUNT(slice_imar) > 0 )
          ERROR_exit("can't mix -byslice and -slicevector") ;
        DT_byslice++ ; nopt++ ; continue ;
#else
        ERROR_exit("-byslice is no longer suppported") ;
#endif
      }

      /**** -normalize [23 Nov 1999] ****/

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

      /**** -vector ****/

      if( strncmp(argv[nopt],"-vector",4) == 0 ){
        MRI_IMAGE * flim ;
        nopt++ ;
        if( nopt >= argc ) ERROR_exit("need argument after -vector") ;
        flim = mri_read_1D( argv[nopt++] ) ;
        if( flim == NULL ) ERROR_exit("can't read -vector '%s'",argv[nopt-1]) ;
        ADDTO_IMARR(DT_imar,flim) ;
        if( DT_verb ) INFO_message("Read file %s: rows=%d cols=%d",
                                   argv[nopt-1],flim->ny,flim->nx ) ;
        continue ;
      }

      /**** -slicevector ****/

      if( strncmp(argv[nopt],"-slicevector",6) == 0 ){
        MRI_IMAGE *flim ;
        nopt++ ;
        if( nopt >= argc ) ERROR_exit("need argument after -slicevector") ;
#ifdef ALLOW_BYSLICE
        if( DT_byslice )   ERROR_exit("can't mix -slicevector and -byslice") ;
#endif
        flim = mri_read_1D( argv[nopt++] ) ;
        if( flim == NULL ) ERROR_exit("can't read -slicevector '%s'",argv[nopt-1]) ;
        ADDTO_IMARR(slice_imar,flim) ;
        if( DT_verb ) INFO_message("Read file %s: rows=%d cols=%d",
                                   argv[nopt-1],flim->ny,flim->nx ) ;
        continue ;
      }

      /**** -del ****/

      if( strncmp(argv[nopt],"-del",4) == 0 ){
        nopt++ ;
        if( nopt >= argc ) ERROR_exit("need argument after -del") ;
        DT_current_del = strtod( argv[nopt++] , NULL ) ;
        if( DT_verb )
          INFO_message("Set expression stepsize = %g\n",DT_current_del) ;
        continue ;
      }

      /**** -expr ****/

      if( strncmp(argv[nopt],"-expr",4) == 0 ){
        int nexp , qvar , kvar ;
        char sym[4] ;

        nopt++ ;
        if( nopt >= argc ) ERROR_exit("need argument after -expr") ;

        nexp = DT_exnum + 1 ;
        if( DT_exnum == 0 ){   /* initialize storage */
          DT_expr   = (char **)        malloc( sizeof(char *) ) ;
          DT_excode = (PARSER_code **) malloc( sizeof(PARSER_code *) ) ;
          DT_exdel  = (float *)        malloc( sizeof(float) ) ;
          DT_exvar  = (int *)          malloc( sizeof(int) ) ;
        } else {
          DT_expr   = (char **)        realloc( DT_expr ,
                                                sizeof(char *)*nexp ) ;
          DT_excode = (PARSER_code **) realloc( DT_excode ,
                                                sizeof(PARSER_code *)*nexp ) ;
          DT_exdel  = (float *)        realloc( DT_exdel ,
                                                sizeof(float)*nexp) ;
          DT_exvar  = (int *)          realloc( DT_exvar ,
                                                sizeof(int)*nexp) ;
        }
        DT_expr[DT_exnum]   = argv[nopt] ;                         /* string */
        DT_exdel[DT_exnum]  = DT_current_del ;                     /* delta */
        DT_excode[DT_exnum] = PARSER_generate_code( argv[nopt] ) ; /* compile */
        if( DT_excode[DT_exnum] == NULL )
          ERROR_exit("Illegal expression: '%s'",argv[nopt]) ;

        qvar = 0 ; kvar = -1 ;                       /* find symbol */
        for( ii=0 ; ii < 26 ; ii++ ){
          sym[0] = 'A' + ii ; sym[1] = '\0' ;
          if( PARSER_has_symbol(sym,DT_excode[DT_exnum]) ){
            qvar++ ; if( kvar < 0 ) kvar = ii ;
            if( DT_verb )
              INFO_message("Found expression symbol %s\n",sym) ;
          }
        }
        if( qvar > 1 )
          ERROR_exit("-expr '%s' has too many symbols",DT_expr[DT_exnum]) ;
        else if( qvar == 0 )
          WARNING_message("-expr '%s' is constant",DT_expr[DT_exnum]) ;
        DT_exvar[DT_exnum] = kvar ;
        DT_exnum = nexp ; nopt++ ; continue ;
      }

      /**** ERROR ****/

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

   }  /* end of scan over options */

   /*-- check for errors --*/

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

#ifdef ALLOW_BYSLICE
   if( IMARR_COUNT(slice_imar) > 0 && DT_byslice )
     ERROR_exit("Illegal mixing of -slicevector and -byslice") ;
#endif

   DT_nvector = IMARR_COUNT(DT_imar) ;
   if( DT_nvector + DT_exnum == 0 && DT_polort < 0 )
     ERROR_exit("No detrending options ordered!") ;

#ifdef ALLOW_BYSLICE
   if( DT_nvector == 0 && DT_byslice )
     ERROR_exit("No -vector option supplied with -byslice!") ;
#endif

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

   DT_dset = THD_open_dataset( argv[nopt] ) ;
   CHECK_OPEN_ERROR(DT_dset,argv[nopt]) ;
   if( DT_dset == NULL )
     ERROR_exit("Can't open dataset %s\n",argv[nopt]) ;

   DT_current_del = DSET_TR(DT_dset) ;
   if( DT_current_del <= 0.0 ){
     DT_current_del = 1.0 ;
     if( DT_verb )
       WARNING_message("Input has no TR value; setting TR=1.0\n") ;
   } else if( DT_verb ){
     INFO_message("Input has TR=%g\n",DT_current_del) ;
   }

   /*-- check vectors for good size --*/

   nvcheck = nvals = DSET_NVALS(DT_dset) ;
#ifdef ALLOW_BYSLICE
   if( DT_byslice ) nvcheck *= DSET_NZ(DT_dset) ;
#endif
   for( ii=0 ; ii < DT_nvector ; ii++ ){
     if( IMARR_SUBIMAGE(DT_imar,ii)->nx < nvcheck ){
       ERROR_message("%d-th -vector is shorter (%d) than dataset (%d)",
                     ii+1,IMARR_SUBIMAGE(DT_imar,ii)->nx,nvcheck) ;
       nerr++ ;
     }
   }
   if( nerr > 0 ) ERROR_exit("Cannot continue") ;

   /*--- create time series from expressions */

   if( DT_exnum > 0 ){
     double atoz[26] , del ;
     int kvar , jj ;
     MRI_IMAGE *flim ;
     float *flar ;

     for( jj=0 ; jj < DT_exnum ; jj++ ){
       if( DT_verb ) INFO_message("Evaluating %d-th -expr\n",jj+1) ;
       kvar = DT_exvar[jj] ;
       del  = DT_exdel[jj] ;
       if( del <= 0.0 ) del = DT_current_del ;
       flim = mri_new( nvals , 1 , MRI_float ) ;
       flar = MRI_FLOAT_PTR(flim) ;
       for( ii=0 ; ii < 26 ; ii++ ) atoz[ii] = 0.0 ;
       for( ii=0 ; ii < nvals ; ii++ ){
         if( kvar >= 0 ) atoz[kvar] = ii * del ;
         flar[ii]   = PARSER_evaluate_one( DT_excode[jj] , atoz ) ;
       }
       ADDTO_IMARR( DT_imar , flim ) ;
     }
   }

   /*--- from polort [10 Apr 2006] ---*/

   if( DT_polort >= 0 ){
     int kk ;
     MRI_IMAGE *flim ;
     float *flar ; double fac=2.0/(nvals-1.0) ;

     for( kk=0 ; kk <= DT_polort ; kk++ ){
       flim = mri_new( nvals , 1 , MRI_float ) ;
       flar = MRI_FLOAT_PTR(flim) ;
       for( ii=0 ; ii < nvals ; ii++ ) flar[ii] = Plegendre(fac*ii-1.0,kk) ;
       ADDTO_IMARR( DT_imar , flim ) ;
     }
   }

   return ;
}
Esempio n. 6
0
int main( int argc , char * argv[] )
{
   int iv,nvals , nvec , ii,jj,kk , nvox ;
   THD_3dim_dataset * new_dset=NULL ;
   double * choleski ;
   float ** refvec , * fv , * fc , * fit ;
   MRI_IMAGE * flim ;

   /*** read input options ***/

   if( argc < 2 || strncmp(argv[1],"-help",4) == 0 ) DT_Syntax() ;

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

   mainENTRY("3dDetrend main"); machdep() ; PRINT_VERSION("3dDetrend");
   AFNI_logger("3dDetrend",argc,argv) ;
   { int new_argc ; char ** new_argv ;
     addto_args( argc , argv , &new_argc , &new_argv ) ;
     if( new_argv != NULL ){ argc = new_argc ; argv = new_argv ; }
   }

   DT_read_opts( argc , argv ) ;

   /*** create new dataset (empty) ***/

   new_dset = EDIT_empty_copy( DT_dset ) ; /* make a copy of its header */

   /* modify its header */

   tross_Copy_History( DT_dset , new_dset ) ;
   tross_Make_History( "3dDetrend" , argc,argv , new_dset ) ;

   EDIT_dset_items( new_dset ,
                      ADN_prefix        , DT_output_prefix ,
                      ADN_directory_name, DT_session ,
                    ADN_none ) ;

   /* can't re-write existing dataset */

   if( THD_deathcon() && THD_is_file(DSET_HEADNAME(new_dset)) )
     ERROR_exit("File %s already exists!\n",DSET_HEADNAME(new_dset) ) ;

   /* read input in, and attach its bricks to the output dataset */
   /* (not good in a plugin, but OK in a standalone program!)    */

   if( DT_verb ) INFO_message("Loading input dataset bricks\n") ;

   DSET_mallocize( new_dset ) ;
   DSET_mallocize( DT_dset ) ;
   DSET_load( DT_dset ) ; CHECK_LOAD_ERROR(DT_dset) ;

   nvals = DSET_NVALS(new_dset) ;
   for( iv=0 ; iv < nvals ; iv++ )
     EDIT_substitute_brick( new_dset , iv ,
                            DSET_BRICK_TYPE(DT_dset,iv) ,
                            DSET_ARRAY(DT_dset,iv)       ) ;

   if( DT_norm && DSET_BRICK_TYPE(new_dset,0) != MRI_float ){
     INFO_message("Turning -normalize option off (input not in float format)");
     DT_norm = 0 ;
   }

   /* load reference (detrending) vectors;
      setup to do least squares fitting of each voxel */

   nvec = 0 ;
   for( ii=0 ; ii < IMARR_COUNT(DT_imar) ; ii++ )  /* number of detrending vectors */
      nvec += IMARR_SUBIMAGE(DT_imar,ii)->ny ;

   refvec = (float **) malloc( sizeof(float *)*nvec ) ;
   for( kk=ii=0 ; ii < IMARR_COUNT(DT_imar) ; ii++ ){
     fv = MRI_FLOAT_PTR( IMARR_SUBIMAGE(DT_imar,ii) ) ;
     for( jj=0 ; jj < IMARR_SUBIMAGE(DT_imar,ii)->ny ; jj++ )         /* compute ptr */
       refvec[kk++] = fv + ( jj * IMARR_SUBIMAGE(DT_imar,ii)->nx ) ;  /* to vectors  */
   }

   fit = (float *) malloc( sizeof(float) * nvals ) ;  /* will get fit to voxel data */

   /*--- do the all-voxels-together case ---*/

   if( !DT_byslice ){
      choleski = startup_lsqfit( nvals , NULL , nvec , refvec ) ;
      if( choleski == NULL )
        ERROR_exit("Choleski factorization fails: linearly dependent vectors!\n") ;

      /* loop over voxels, fitting and detrending (or replacing) */

      nvox = DSET_NVOX(new_dset) ;

      if( DT_verb ) INFO_message("Computing voxel fits\n") ;

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

         flim = THD_extract_series( kk , new_dset , 0 ) ;              /* data */
         fv   = MRI_FLOAT_PTR(flim) ;
         fc   = delayed_lsqfit( nvals, fv, nvec, refvec, choleski ) ;  /* coef */

         for( ii=0 ; ii < nvals ; ii++ ) fit[ii] = 0.0 ;

         for( jj=0 ; jj < nvec ; jj++ )
            for( ii=0 ; ii < nvals ; ii++ )
               fit[ii] += fc[jj] * refvec[jj][ii] ;                    /* fit */

         if( !DT_replace )                                             /* remove */
            for( ii=0 ; ii < nvals ; ii++ ) fit[ii] = fv[ii] - fit[ii] ;

         if( DT_norm ) THD_normalize( nvals , fit ) ;  /* 23 Nov 1999 */

         THD_insert_series( kk, new_dset, nvals, MRI_float, fit, 0 ) ;

         free(fc) ; mri_free(flim) ;
      }

      free(choleski) ;

      /*- end of all-voxels-together case -*/

   }
#ifdef ALLOW_BYSLICE
     else {                                 /*- start of slice case [08 Dec 1999] -*/
      int ksl , nslice , tt , nx,ny , nxy , kxy ;
      MRI_IMAGE * vim ;

      /* make separate space for the slice-wise detrending vectors */

      for( kk=ii=0 ; ii < DT_nvector ; ii++ ){
         for( jj=0 ; jj < IMARR_SUBIMAGE(DT_imar,ii)->ny ; jj++ )       /* replace ptrs */
            refvec[kk++] = (float *) malloc( sizeof(float) * nvals ) ;  /* to vectors   */
      }

      nslice = DSET_NZ(new_dset) ;
      nxy    = DSET_NX(new_dset) * DSET_NY(new_dset) ;

      /* loop over slices */

      for( ksl=0 ; ksl < nslice ; ksl++ ){

         if( DT_verb ) INFO_message("Computing voxel fits for slice %d\n",ksl) ;

         /* extract slice vectors from input interlaced vectors */

         for( kk=ii=0 ; ii < DT_nvector ; ii++ ){        /* loop over vectors */
            vim = IMARR_SUBIMAGE(DT_imar,ii) ;           /* ii-th vector image */
            nx = vim->nx ; ny = vim->ny ;                /* dimensions */
            for( jj=0 ; jj < ny ; jj++ ){                /* loop over columns */
               fv = MRI_FLOAT_PTR(vim) + (jj*nx) ;       /* ptr to column */
               for( tt=0 ; tt < nvals ; tt++ )           /* loop over time */
                  refvec[kk][tt] = fv[ksl+tt*nslice] ;   /* data point */
            }
         }

         /* initialize fitting for this slice */

         choleski = startup_lsqfit( nvals , NULL , nvec , refvec ) ;
         if( choleski == NULL )
           ERROR_exit("Choleski fails: linearly dependent vectors at slice %d\n",ksl) ;

         /* loop over voxels in this slice */

         for( kxy=0 ; kxy < nxy ; kxy++ ){

            kk   = kxy + ksl*nxy ;                                        /* 3D index */
            flim = THD_extract_series( kk , new_dset , 0 ) ;              /* data */
            fv   = MRI_FLOAT_PTR(flim) ;
            fc   = delayed_lsqfit( nvals, fv, nvec, refvec, choleski ) ;  /* coef */

            for( ii=0 ; ii < nvals ; ii++ ) fit[ii] = 0.0 ;

            for( jj=0 ; jj < nvec ; jj++ )
               for( ii=0 ; ii < nvals ; ii++ )
                  fit[ii] += fc[jj] * refvec[jj][ii] ;                    /* fit */

            if( !DT_replace )                                             /* remove */
               for( ii=0 ; ii < nvals ; ii++ ) fit[ii] = fv[ii] - fit[ii] ;

            if( DT_norm ) THD_normalize( nvals , fit ) ;  /* 23 Nov 1999 */

            THD_insert_series( kk, new_dset, nvals, MRI_float, fit, 0 ) ;

            free(fc) ; mri_free(flim) ;
         }

         free(choleski) ;

      } /* end of loop over slices */

   } /*- end of -byslice case -*/
#endif

   /*-- done done done done --*/

   DSET_write(new_dset) ;
   if( DT_verb ) WROTE_DSET(new_dset) ;
   exit(0) ;
}
Esempio n. 7
0
MRI_IMARR * THD_extract_many_series( int ns, int *ind, THD_3dim_dataset *dset )
{
   MRI_IMARR *imar ; /* output */
   MRI_IMAGE *im ;
   int nv , ival , kk ;
   char *iar ;      /* brick in the input */
   float **far ;    /* 27 Feb 2003: ptrs to output */

ENTRY("THD_extract_many_series") ;

   if( ns <= 0 || ind == NULL | dset == NULL ) RETURN( NULL );

   /* try to load dataset */

   nv  = dset->dblk->nvals ;
   iar = DSET_ARRAY(dset,0) ;
   if( iar == NULL ){  /* if data needs to be loaded from disk */
     (void) THD_load_datablock( dset->dblk ) ;
     iar = DSET_ARRAY(dset,0) ;
     if( iar == NULL ){
       static int nerr=0 ;
       if( nerr < 2 ){ ERROR_message("Can't load dataset %s",DSET_HEADNAME(dset)); nerr++; }
       RETURN( NULL );
     }
   }

   /* create output */

   far = (float **) malloc(sizeof(float *)*ns) ;  /* 27 Feb 2003 */
   NULL_CHECK(far) ;
   INIT_IMARR(imar) ;
   for( kk=0 ; kk < ns ; kk++ ){
     im = mri_new( nv , 1 , MRI_float ) ;  /* N.B.: now does 0 fill */
     far[kk] = MRI_FLOAT_PTR(im) ;         /* ptr to kk-th output series */
     ADDTO_IMARR(imar,im) ;
   }

   /* fill the output */

   switch( DSET_BRICK_TYPE(dset,0) ){

      default:             /* don't know what to do --> return nada */
        DESTROY_IMARR(imar) ; free(far) ;
        RETURN( NULL );

      case MRI_byte:{
        byte * bar ;
        for( ival=0 ; ival < nv ; ival++ ){
          bar = (byte *) DSET_ARRAY(dset,ival) ;
          if( bar != NULL ){
            for( kk=0 ; kk < ns ; kk++ ){
              far[kk][ival] = (float)bar[ind[kk]] ;
            }
          }
        }
      }
      break ;

      case MRI_short:{
        short * bar ;
        for( ival=0 ; ival < nv ; ival++ ){
          bar = (short *) DSET_ARRAY(dset,ival) ;
          if( bar != NULL ){
            for( kk=0 ; kk < ns ; kk++ ){
              far[kk][ival] = (float)bar[ind[kk]] ;
            }
          }
        }
      }
      break ;

      case MRI_float:{
         float * bar ;
         for( ival=0 ; ival < nv ; ival++ ){
            bar = (float *) DSET_ARRAY(dset,ival) ;
            if( bar != NULL ){
              for( kk=0 ; kk < ns ; kk++ ){
                 far[kk][ival] = bar[ind[kk]] ;
              }
            }
         }
      }
      break ;

#if 0
      case MRI_int:{
         int * bar ;
         for( ival=0 ; ival < nv ; ival++ ){
            bar = (int *) DSET_ARRAY(dset,ival) ;
            if( bar != NULL ){
              for( kk=0 ; kk < ns ; kk++ ){
                 far[kk][ival] = bar[ind[kk]] ;
              }
            }
         }
      }
      break ;

      case MRI_double:{
         double * bar ;
         for( ival=0 ; ival < nv ; ival++ ){
            bar = (double *) DSET_ARRAY(dset,ival) ;
            if( bar != NULL ){
              for( kk=0 ; kk < ns ; kk++ ){
                 far[kk][ival] = (float)bar[ind[kk]] ;
              }
            }
         }
      }
      break ;
#endif

      case MRI_complex:{
         complex * bar ;
         for( ival=0 ; ival < nv ; ival++ ){
            bar = (complex *) DSET_ARRAY(dset,ival) ;
            if( bar != NULL ){
              for( kk=0 ; kk < ns ; kk++ ){
                 far[kk][ival] = bar[ind[kk]].r ;
              }
            }
         }
      }
      break ;

   }

   /* scale outputs, if needed */

   if( THD_need_brick_factor(dset) ){
      MRI_IMAGE *qim ;
      for( kk=0 ; kk < ns ; kk++ ){
         im  = IMARR_SUBIMAGE(imar,kk) ;
         qim = mri_mult_to_float( dset->dblk->brick_fac , im ) ;
         mri_free(im) ;
         IMARR_SUBIMAGE(imar,kk) = qim ;
      }
   }

#if 0  /* 27 Feb 2003 */
   /* convert to floats, if needed */

   if( IMARR_SUBIMAGE(imar,0)->kind != MRI_float ){
      MRI_IMAGE * qim ;
      for( kk=0 ; kk < ns ; kk++ ){
         im  = IMARR_SUBIMAGE(imar,kk) ;
         qim = mri_to_float( im ) ;
         mri_free(im) ;
         IMARR_SUBIMAGE(imar,kk) = qim ;
      }
   }
#endif

   /* add time axis stuff to output images, if present */

   if( dset->taxis != NULL ){
      float zz , tt ;
      int kz ;

      for( kk=0 ; kk < ns ; kk++ ){
         kz = ind[kk] / ( dset->daxes->nxx * dset->daxes->nyy ) ;
         zz = dset->daxes->zzorg + kz * dset->daxes->zzdel ;
         tt = THD_timeof( 0 , zz , dset->taxis ) ;
         im = IMARR_SUBIMAGE(imar,kk) ;
         im->xo = tt ; im->dx = dset->taxis->ttdel ;   /* origin and delta */
         if( dset->taxis->units_type == UNITS_MSEC_TYPE ){ /* convert to sec */
            im->xo *= 0.001 ; im->dx *= 0.001 ;
         }
      }
   } else {
      for( kk=0 ; kk < ns ; kk++ ){
         im = IMARR_SUBIMAGE(imar,kk) ;
         im->xo = 0.0 ; im->dx = 1.0 ;
      }
   }

   free(far) ; RETURN(imar);
}
Esempio n. 8
0
char * IMREG_main( PLUGIN_interface * plint )
{
    MCW_idcode * idc ;                          /* input dataset idcode */
    THD_3dim_dataset * old_dset , * new_dset ;  /* input and output datasets */
    char * new_prefix , * str ;                 /* strings from user */
    int base , ntime , datum , nx,ny,nz , ii,kk , npix ;
    float                      dx,dy,dz ;
    MRI_IMARR * ims_in , * ims_out ;
    MRI_IMAGE * im , * imbase ;

    byte   ** bptr = NULL , ** bout = NULL ;
    short  ** sptr = NULL , ** sout = NULL ;
    float  ** fptr = NULL , ** fout = NULL ;

    float * dxar = NULL , * dyar = NULL , * phiar = NULL ;

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

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

    PLUTO_next_option(plint) ;

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

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

    ii = DSET_NVALS_PER_TIME(old_dset) ;
    if( ii > 1 )
        return "************************************\n"
               "Dataset has > 1 value per time point\n"
               "************************************"  ;

    nx = old_dset->daxes->nxx ;
    dx = old_dset->daxes->xxdel ;
    ny = old_dset->daxes->nyy ;
    dy = old_dset->daxes->yydel ;
    npix = nx*ny ;
    nz = old_dset->daxes->nzz ;
    dz = old_dset->daxes->zzdel ;

    if( nx != ny || fabs(dx) != fabs(dy) ) {

#ifdef IMREG_DEBUG
        fprintf(stderr,"\nIMREG: nx=%d ny=%d nz=%d  dx=%f dy=%f dz=%f\n",
                nx,ny,nz,dx,dy,dz ) ;
#endif

        return "***********************************\n"
               "Dataset does not have square slices\n"
               "***********************************"  ;
    }

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

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

    PLUTO_next_option(plint) ;

    base = PLUTO_get_number(plint) ;
    if( base >= ntime )
        return "********************\n"
               "Base value too large\n"
               "********************"  ;

    /*--------- see if the 3rd option line is present --------*/

    str = PLUTO_get_optiontag( plint ) ;
    if( str != NULL ) {
        float fsig , fdxy , fdph ;
        fsig = PLUTO_get_number(plint) * 0.42466090 ;
        fdxy = PLUTO_get_number(plint) ;
        fdph = PLUTO_get_number(plint) ;
        mri_align_params( 0 , 0.0,0.0,0.0 , fsig,fdxy,fdph ) ;
        /* fprintf(stderr,"Set fine params = %f %f %f\n",fsig,fdxy,fdph) ; */
    }

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

#ifdef IMREG_DEBUG
    fprintf(stderr,"IMREG: loading dataset\n") ;
#endif

    DSET_load( old_dset ) ;

    /*** 1) Copy the dataset in toto ***/

#ifdef IMREG_DEBUG
    fprintf(stderr,"IMREG: Copying dataset\n") ;
#endif

    new_dset = PLUTO_copy_dset( old_dset , new_prefix ) ;
    if( new_dset == NULL )
        return "****************************\n"
               "Failed to copy input dataset\n"
               "****************************"  ;

    /*** 2) Make an array of empty images ***/

#ifdef IMREG_DEBUG
    fprintf(stderr,"IMREG: making empty images\n") ;
#endif

    datum = DSET_BRICK_TYPE(new_dset,0) ;

    INIT_IMARR(ims_in) ;
    for( ii=0 ; ii < ntime ; ii++ ) {
        im = mri_new_vol_empty( nx , ny , 1 , datum ) ;
        ADDTO_IMARR(ims_in,im) ;
    }

    imbase = mri_new_vol_empty( nx , ny , 1 , datum ) ;

    dxar  = (float *) malloc( sizeof(float) * ntime ) ;
    dyar  = (float *) malloc( sizeof(float) * ntime ) ;
    phiar = (float *) malloc( sizeof(float) * ntime ) ;

    /*** 3) Get pointers to sub-bricks in old and new datasets ***/

#ifdef IMREG_DEBUG
    fprintf(stderr,"IMREG: getting input brick pointers\n") ;
#endif

    switch( datum ) { /* pointer type depends on input datum type */
    case MRI_byte:
        bptr = (byte **) malloc( sizeof(byte *) * ntime ) ;
        bout = (byte **) malloc( sizeof(byte *) * ntime ) ;
        for( ii=0 ; ii < ntime ; ii++ ) {
            bptr[ii] = (byte *) DSET_ARRAY(old_dset,ii) ;
            bout[ii] = (byte *) DSET_ARRAY(new_dset,ii) ;
        }
        break ;

    case MRI_short:
        sptr = (short **) malloc( sizeof(short *) * ntime ) ;
        sout = (short **) malloc( sizeof(short *) * ntime ) ;
        for( ii=0 ; ii < ntime ; ii++ ) {
            sptr[ii] = (short *) DSET_ARRAY(old_dset,ii) ;
            sout[ii] = (short *) DSET_ARRAY(new_dset,ii) ;
        }

#ifdef IMREG_DEBUG
        fprintf(stderr,"IMREG: sptr[0] = %p  sout[0] = %p\n",sptr[0],sout[0]) ;
#endif

        break ;

    case MRI_float:
        fptr = (float **) malloc( sizeof(float *) * ntime ) ;
        fout = (float **) malloc( sizeof(float *) * ntime ) ;
        for( ii=0 ; ii < ntime ; ii++ ) {
            fptr[ii] = (float *) DSET_ARRAY(old_dset,ii) ;
            fout[ii] = (float *) DSET_ARRAY(new_dset,ii) ;
        }
        break ;
    }

    /*** 4) Loop over slices ***/

    PLUTO_popup_meter(plint) ;

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

        /*** 4a) Setup ims_in images to point to input slices ***/

#ifdef IMREG_DEBUG
        fprintf(stderr,"IMREG: slice %d -- setup input images\n",kk) ;
#endif

        for( ii=0 ; ii < ntime ; ii++ ) {
            im = IMARR_SUBIMAGE(ims_in,ii) ;
            switch( datum ) {
            case MRI_byte:
                mri_fix_data_pointer( bptr[ii] + kk*npix, im ) ;
                break ;
            case MRI_short:
                mri_fix_data_pointer( sptr[ii] + kk*npix, im ) ;
                break ;
            case MRI_float:
                mri_fix_data_pointer( fptr[ii] + kk*npix, im ) ;
                break ;
            }
        }

        /*** 4b) Setup im to point to base image ***/

#ifdef IMREG_DEBUG
        fprintf(stderr,"IMREG: slice %d -- setup base image\n",kk) ;
#endif

        switch( datum ) {
        case MRI_byte:
            mri_fix_data_pointer( bptr[base] + kk*npix, imbase ) ;
            break ;
        case MRI_short:
            mri_fix_data_pointer( sptr[base] + kk*npix, imbase ) ;
            break ;
        case MRI_float:
            mri_fix_data_pointer( fptr[base] + kk*npix, imbase ) ;
            break ;
        }

        /*** 4c) Register this slice at all times ***/

#ifdef IMREG_DEBUG
        fprintf(stderr,"IMREG: slice %d -- register\n",kk) ;
#endif

        ims_out = mri_align_dfspace( imbase , NULL , ims_in ,
                                     ALIGN_REGISTER_CODE , dxar,dyar,phiar ) ;

        if( ims_out == NULL )
            fprintf(stderr,"IMREG: mri_align_dfspace return NULL\n") ;

        /*** 4d) Put the output back in on top of the input;
                 note that the output is always in MRI_float format ***/

#ifdef IMREG_DEBUG
        fprintf(stderr,"IMREG: slice %d -- put output back into dataset\n",kk) ;
#endif

        for( ii=0 ; ii < ntime ; ii++ ) {
            switch( datum ) {
            case MRI_byte:
                im = mri_to_mri( MRI_byte , IMARR_SUBIMAGE(ims_out,ii) ) ;
                memcpy( bout[ii] + kk*npix , MRI_BYTE_PTR(im) , sizeof(byte)*npix ) ;
                mri_free(im) ;
                break ;

            case MRI_short:
#ifdef IMREG_DEBUG
                if( ii==0 )fprintf(stderr,"IMREG: conversion to short at ii=%d\n",ii) ;
#endif

                im = mri_to_mri( MRI_short , IMARR_SUBIMAGE(ims_out,ii) ) ;

#ifdef IMREG_DEBUG
                if( ii==0 )fprintf(stderr,"IMREG: copying to %p from %p\n",sout[ii] + kk*npix,MRI_SHORT_PTR(im)) ;
#endif

                memcpy( sout[ii] + kk*npix , MRI_SHORT_PTR(im) , sizeof(short)*npix ) ;

#ifdef IMREG_DEBUG
                if( ii==0 )fprintf(stderr,"IMREG: freeing\n") ;
#endif

                mri_free(im) ;
                break ;

            case MRI_float:
                im = IMARR_SUBIMAGE(ims_out,ii) ;
                memcpy( fout[ii] + kk*npix , MRI_FLOAT_PTR(im) , sizeof(float)*npix ) ;
                break ;
            }
        }

        PLUTO_set_meter(plint, (100*(kk+1))/nz ) ;

        /*** 4e) Destroy the output images ***/

#ifdef IMREG_DEBUG
        fprintf(stderr,"IMREG: destroying aligned output\n") ;
#endif

        DESTROY_IMARR( ims_out ) ;
    }

    /*** 5) Destroy the empty images and other workspaces ***/

#ifdef IMREG_DEBUG
    fprintf(stderr,"IMREG: destroy workspaces\n") ;
#endif

    mri_clear_data_pointer(imbase) ;
    mri_free(imbase) ;
    for( ii=0 ; ii < ntime ; ii++ ) {
        im = IMARR_SUBIMAGE(ims_in,ii) ;
        mri_clear_data_pointer(im) ;
    }
    DESTROY_IMARR(ims_in) ;
    FREE_WORKSPACE ;

    /*------------- let AFNI know about the new dataset ------------*/

#ifdef IMREG_DEBUG
    fprintf(stderr,"IMREG: send result to AFNI\n") ;
#endif

    PLUTO_add_dset( plint , new_dset , DSET_ACTION_MAKE_CURRENT ) ;

    return NULL ;  /* null string returned means all was OK */
}