#include "mrilib.h"

THD_fvec3 THD_cmass( THD_3dim_dataset *xset , int iv , byte *mmm ) ;

int main( int argc , char * argv[] )
{
   int narg=1, do_automask=0 , iv , nxyz , do_set=0 ;
   THD_3dim_dataset *xset ;
   byte *mmm=NULL ; int nmask=0 , nvox_mask ;
   THD_fvec3 cmv , setv ;
   /*-- read command line arguments --*/

   if( argc < 2 || strncmp(argv[1],"-help",5) == 0 ){
      printf("Usage: 3dCM [options] dset\n"
             "Output = center of mass of dataset, to stdout.\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"
             "  -automask    Generate the mask automatically.\n"
             "  -set x y z   After computing the CM of the dataset, set the\n"
             "                 origin fields in the header so that the CM\n"
             "                 will be at (x,y,z) in DICOM coords.\n"
            ) ;
      exit(0) ;
   }

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

      if( strcmp(argv[narg],"-set") == 0 ){
        float xset,yset,zset ;
        if( narg+3 >= argc ){
          fprintf(stderr,"*** -set need 3 args following!\n") ; exit(1) ;
        }
        xset = strtod( argv[++narg] , NULL ) ;
        yset = strtod( argv[++narg] , NULL ) ;
        zset = strtod( argv[++narg] , NULL ) ;
        LOAD_FVEC3(setv,xset,yset,zset) ; do_set = 1 ;
        THD_set_write_compression(COMPRESS_NONE); /* do not alter compression*/
        narg++ ; continue ;
      }

      if( strncmp(argv[narg],"-mask",5) == 0 ){
        THD_3dim_dataset *mask_dset ;
        if( mmm != NULL ){
          fprintf(stderr,"*** Cannot have two -mask options!\n") ; exit(1) ;
        }
        if( do_automask ){
          fprintf(stderr,"*** Can't have -mask and -automask!\n") ; exit(1) ;
        }
        if( narg+1 >= argc ){
          fprintf(stderr,"*** -mask option requires a following argument!\n");
          exit(1) ;
        }
        mask_dset = THD_open_dataset( argv[++narg] ) ;
        CHECK_OPEN_ERROR(mask_dset,argv[narg]) ;
        if( DSET_BRICK_TYPE(mask_dset,0) == MRI_complex ){
          fprintf(stderr,"*** Cannot deal with complex-valued mask dataset!\n");
          exit(1) ;
        }
        mmm = THD_makemask( mask_dset , 0 , 1.0,0.0 ) ;
        nvox_mask = DSET_NVOX(mask_dset) ;
        nmask = THD_countmask( nvox_mask , mmm ) ;
        if( mmm == NULL || nmask <= 0 ){
          fprintf(stderr,"*** Can't make mask from dataset %s\n",argv[narg-1]);
          exit(1) ;
        }
        DSET_delete( mask_dset ) ;
        narg++ ; continue ;
      }

      if( strcmp(argv[narg],"-automask") == 0 ){
        if( mmm != NULL ){
          fprintf(stderr,"*** Can't have -mask and -automask!\n") ; exit(1) ;
        }
        do_automask = 1 ; narg++ ; continue ;
      }

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

   /* should have at least 1 more argument */

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

   for( ; narg < argc ; narg++ ){
     xset = THD_open_dataset( argv[narg] ) ;
     if( xset == NULL ){
       fprintf(stderr,"+++ Can't open dataset %s -- skipping\n",argv[narg]);
       continue ;
     }
     DSET_load(xset) ;
     if( !DSET_LOADED(xset) ){
       fprintf(stderr,"+++ Can't load dataset %s -- skipping\n",argv[narg]);
       DSET_delete(xset) ; continue ;
     }
     if( do_automask ){
       if( mmm != NULL ){ free(mmm); mmm = NULL; }
       mmm = THD_automask(xset) ;
       nvox_mask = DSET_NVOX(xset) ;
       nmask = THD_countmask( nvox_mask , mmm ) ;
       if( mmm == NULL || nmask <= 0 ){
         fprintf(stderr,"+++ Can't make automask from dataset %s -- skipping\n",argv[narg]) ;
         DSET_delete(xset) ; continue ;
       }
     }
     nxyz = DSET_NVOX(xset) ;
     if( mmm != NULL && nxyz != nvox_mask ){
       fprintf(stderr,"+++ Mask/Dataset grid size mismatch at %s\n -- skipping\n",argv[narg]) ;
       DSET_delete(xset) ; continue ;
     }

     cmv = THD_cmass( xset , 0 , mmm ) ;
     printf("%g  %g  %g\n",cmv.xyz[0],cmv.xyz[1],cmv.xyz[2]) ;
      DSET_unload(xset) ;

     if( do_set ){
       THD_fvec3 dv , ov ;
       if(  DSET_IS_MASTERED(xset) ){
         fprintf(stderr,"+++ Can't modify CM of dataset %s\n",argv[narg]) ;
       } else {
         LOAD_FVEC3(ov,DSET_XORG(xset),DSET_YORG(xset),DSET_ZORG(xset)) ;
         ov = THD_3dmm_to_dicomm( xset , ov ) ;
         dv = SUB_FVEC3(setv,cmv) ;
         ov = ADD_FVEC3(dv,ov) ;
         ov = THD_dicomm_to_3dmm( xset , ov ) ;
         xset->daxes->xxorg = ov.xyz[0] ;
         xset->daxes->yyorg = ov.xyz[1] ;
         xset->daxes->zzorg = ov.xyz[2] ;
         /* allow overwriting header for all types of output data */
         putenv("AFNI_DONT_DECONFLICT=YES") ;
	 if(DSET_IS_BRIK(xset)) {
           INFO_message("Rewriting header %s",DSET_HEADNAME(xset)) ;
           DSET_write_header( xset ) ;
	 }
	 else {     /* for other dataset types like NIFTI, rewrite whole dset */
	    DSET_load( xset ) ; THD_load_statistics( xset ) ;
            THD_write_3dim_dataset(NULL,NULL,xset,1); /* rewrite output file */
            INFO_message("Wrote new dataset: %s",DSET_BRIKNAME(xset)) ;
	 }   
      }
     }
     DSET_delete(xset) ;
  }
}

/*----------------------------------------------------------------------*/
/*! Get the center of mass of this volume, in DICOM coords.
------------------------------------------------------------------------*/

THD_fvec3 THD_cmass( THD_3dim_dataset *xset , int iv , byte *mmm )
{
   THD_fvec3 cmv ;
   MRI_IMAGE *im ;
   float *far , icm,jcm,kcm ;
   int ii , nvox ;

   LOAD_FVEC3(cmv,0,0,0) ;

   nvox = DSET_NVOX(xset) ;
   im   = mri_to_float( DSET_BRICK(xset,iv) ) ;
                             if( im  == NULL ) return cmv ;
   far = MRI_FLOAT_PTR(im) ; if( far == NULL ) return cmv ;

   if( mmm != NULL ){
     for( ii=0 ; ii < nvox ; ii++ )
       if( mmm[ii] ) far[ii] = 0.0 ;
   }

   mri_get_cmass_3D( im , &icm,&jcm,&kcm ) ; mri_free(im) ;
   LOAD_FVEC3(cmv,icm,jcm,kcm) ;
   cmv = THD_3dfind_to_3dmm( xset , cmv ) ;
   cmv = THD_3dmm_to_dicomm( xset , cmv ) ;
   return cmv ;
}


syntax highlighted by Code2HTML, v. 0.9.1