#! /bin/tcsh -f


# mri_cvs_register
#
# Wrapper for Combined Volumetric- and Surface-based Registration (CVS)
#
# Original Author: Lilla Zollei
# Created: 10-29-2009
# Edited : 12-11-2009
# Edited : 08-10-2010: added --mpi option
# Edited : 03-17-2011: replaces applyMorph with mri_vol2vol
# Edited : 05-13-2011: deleted --mpi option
# Edited : 08-04-2011: deleting partial files and renaming final output files; 
# also resampling norm / aseg files after nl_align so that only one resampling is done
# Edited : 08-24-2011: added new logfile that should be easier to read for the user
# Edited : 06-03-2012: added new flags --asegfname and --nointensity
# Edited : 12-20-2012: young modulus changed to 1000 for atlases as well; no petsc log written now; 
#                      more timing and launchpad help; openmp option; logfiles written to the outputdir 
#                      and not into current
#
# CVS Revision Info:
#    $Author: nicks $
#    $Date: 2013/02/09 00:37:37 $
#    $Revision: 1.15.2.12 $
#
# Copyright © 2010-2012 The General Hospital Corporation (Boston, MA) "MGH"
#
# Terms and conditions for use, reproduction, distribution and contribution
# are found in the 'FreeSurfer Software License Agreement' contained
# in the file 'LICENSE' found in the FreeSurfer distribution, and here:
#
# https://surfer.nmr.mgh.harvard.edu/fswiki/FreeSurferSoftwareLicense
#
# Reporting: freesurfer@nmr.mgh.harvard.edu
#

set inputargs = ($argv);
set VERSION = '$Id: mri_cvs_register,v 1.15.2.12 2013/02/09 00:37:37 nicks Exp $';

set movingid = ();
set templateid = ();
#set outdir = ();
set cleanup = 1;
set keepelreg = 0;
set keepallm3z = 0;
set usem3d = 0;
set nolog = 0;
set UseAseg = 1;
set UseInt = 1;
set PrintHelp = 0;
set OnlyStep1 = 0
set OnlyStep2 = 0
set OnlyStep3 = 0
set DoAllSteps = 1
set BothHemis = 1
set CleanSurfReg = 0
set CleanElReg = 0
set CleanVolReg = 0
set openmpN = 1

set FStemplate = cvs_avg35
set usingFStemplate = 0
set CVSMNItemplate = cvs_avg35_inMNI152
set usingCVSMNItemplate = 0

set asegfname = aseg

set downsample = 0

# Parsing and checking the input arguments
if($#argv == 0) goto usage_exit;
set n = `echo $argv | egrep -e --version | wc -l`
if($n != 0) then
  echo $VERSION
  exit 0;
endif
set n = `echo $argv | egrep -e --help | wc -l`
if($n != 0) then
  set PrintHelp = 1;
  goto usage_exit;
endif

setenv TEMPLATE_DIR $SUBJECTS_DIR # the default scenario
goto parse_args;
parse_args_return:
goto check_params;
check_params_return:

if (($UseAseg == 0) && ($UseInt == 0)) then
  set DoAllSteps = 0;
endif

### 
setenv OMP_NUM_THREADS $openmpN
###

set StartTime = `date`;
set DateString = "`date '+%y%m%d%H%M'`"

### Creating outputdir
echo The outdir:
if (! $?outdir) then
  set outdir = $SUBJECTS_DIR/$movingid/cvs  
endif
echo $outdir
mkdir -p $outdir

# Setting up the default params and logging utilities 
if(! $nolog) then
  set currdir = `pwd`
  set LF  = $outdir/${movingid}_to_${templateid}.mri_cvs_register.$DateString.log
  set sLF = $outdir/summary.${movingid}_to_${templateid}.mri_cvs_register.$DateString.log
  if(-e $LF) mv $LF $LF.old;
  if(-e $sLF) mv $sLF $sLF.old;
  echo ""
  echo "Log file is $LF"
  echo ""
else
  set LF = /dev/null
endif

echo "Logfile for mri_cvs_register" >> $LF
echo "Summary logfile for mri_cvs_register" >> $sLF
set tmpMsg = `date`
echo $tmpMsg |& tee -a $LF
echo $tmpMsg >> $sLF
echo $inputargs |& tee -a $LF
echo $inputargs >> $sLF
echo $VERSION |& tee -a $LF
echo $VERSION >> $sLF
set tmpMsg = `hostname`
echo $tmpMsg |& tee -a $LF
echo $tmpMsg >> $sLF
set tmpMsg = `uname -a`
echo $tmpMsg |& tee -a $LF
echo $tmpMsg >> $sLF
echo "asegfname $asegfname" | tee -a $sLF | tee -a $LF

############--------------##################

echo "Initializing the mri_cvs_register run" >> $sLF

set voltype = norm
set annotfile = aparc.annot
set cvsdir =  $FREESURFER_HOME/bin

# NOTE: allow saving morphs using m3d, so that gzip errors are eliminated
if ($usem3d) then
  set morphsuffix = m3d
else 
  set morphsuffix = m3z
endif
if ($DoAllSteps || $OnlyStep3) then
  set tmpMsg =  "Using $morphsuffix type morph files."
  echo $tmpMsg |& tee -a $LF
  echo $tmpMsg >> $sLF
endif

### REGISTRATION: STEP 1: #CVS_step1.csh
###     preprocessing: to get mean and Gaussian curvature files (.H, .K) if they do not exist

if ($DoAllSteps || $OnlyStep1) then 

set Step1StartTime = `date +%s`;

set movingsurfdir   = $SUBJECTS_DIR/$movingid/surf 
set templatesurfdir = $TEMPLATE_DIR/$templateid/surf

set movinglabeldir   = $SUBJECTS_DIR/$movingid/label
set templatelabeldir = $TEMPLATE_DIR/$templateid/label

if ($BothHemis) then
  if ((! -e $movingsurfdir/lh.inflated.K ) || (! -e $movingsurfdir/rh.inflated.K) || ( ! -e $movingsurfdir/lh.inflated.H) || (! -e $movingsurfdir/rh.inflated.H)) then
    echo $movingid ': at least one mean and/or Gaussian curvature file is missing (.H, .K)'
    pushd $movingsurfdir
    foreach hemi (lh rh)
      set cmd = (mris_curvature -w -distances 10 10 $hemi.inflated)
      echo $cmd >> $LF
      echo $cmd >> $sLF
      $cmd |& tee -a $LF
      if($status) exit 1;  
    end
    popd
  endif

  if ((! -e $templatesurfdir/lh.inflated.K ) || (! -e $templatesurfdir/rh.inflated.K) || ( ! -e $templatesurfdir/lh.inflated.H) || (! -e $templatesurfdir/rh.inflated.H)) then
    echo $templateid ': at least one mean and/or Gaussian curvature file is missing (.H, .K)'
    pushd $templatesurfdir
    foreach hemi (lh rh)
      set cmd = (mris_curvature -w -distances 10 10 $hemi.inflated)
      echo $cmd >> $LF
      echo $cmd >> $sLF
      $cmd |& tee -a $LF
      if($status) exit 1;  
    end
    popd
  endif
else
  set hemi = $hemiReq
  if ((! -e $movingsurfdir/$hemi.inflated.K ) || ( ! -e $movingsurfdir/$hemi.inflated.H)) then
    echo $movingid ': at least one mean and/or Gaussian curvature file is missing (.H, .K)'
    pushd $movingsurfdir
    set cmd = (mris_curvature -w -distances 10 10 $hemi.inflated)
    echo $cmd >> $LF
    echo $cmd >> $sLF
    $cmd |& tee -a $LF
    if($status) exit 1;  
    popd
  endif

  if ((! -e $templatesurfdir/$hemi.inflated.K ) || ( ! -e $templatesurfdir/$hemi.inflated.H) ) then
    echo $templateid ': at least one mean and/or Gaussian curvature file is missing (.H, .K)'
    pushd $templatesurfdir
    set cmd = (mris_curvature -w -distances 10 10 $hemi.inflated)
    echo $cmd >> $LF
    echo $cmd >> $sLF
    $cmd |& tee -a $LF
    if($status) exit 1;  
    popd
  endif

endif #BothHemis

###     spherical registration (note: this step assumes existence of
###     the ?h.aparc.annot, ?h.white and ?h.pial files)

echo "Ready for spherical registration (CVS: Step 1)" >> $sLF

## Check whether the necessary files in label and surf exist
if ($BothHemis) then
  foreach hemi (lh rh)
    if (!(-e $movinglabeldir/$hemi.$annotfile)) then
      echo 'ERROR: The ' $hemi '.aparc.annot file should be CREATED for subject ' $movingid ' before continuing!'
      exit 1;
    endif
  end #(hemi)
  foreach hemi (lh rh)
    foreach surf (white pial)
      if (!(-e $movingsurfdir/$hemi.$surf) ) then
        echo 'ERROR: The' $hemi '.' $surf ' file should be CREATED for subject ' $movingid ' before continuing!'
        exit 1;
      endif
    end #(surf)
  end #(hemi)
else
  if (!(-e $movinglabeldir/$hemi.$annotfile)) then
    echo 'ERROR: The ' $hemi '.aparc.annot file should be CREATED for subject ' $movingid ' before continuing!'
    exit 1;
  endif
  foreach surf (white pial)
    if (!(-e $movingsurfdir/$hemi.$surf) ) then
      echo 'ERROR: The' $hemi '.' $surf ' file should be CREATED for subject ' $movingid ' before continuing!'
      exit 1;
    endif
  end #(surf)
endif #BothHemis

## Surface-based registration
if ($BothHemis) then
  foreach hemi (lh rh)
    if (!(-e $movingsurfdir/$hemi.cvs.to$templateid.sphere.reg) || $CleanSurfReg) then
      # the spherical registration does not yet exist
      set cmd = (mris_register -1 -dist 1.0 -inflated $movingsurfdir/$hemi.sphere $templatesurfdir/$hemi.sphere $movingsurfdir/$hemi.cvs.to$templateid.sphere.reg)
      echo $cmd >> $LF
      echo $cmd >> $sLF
      $cmd |& tee -a $LF
      if($status) exit 1;
    endif
  end    # (hemi)
else
  if (!(-e $movingsurfdir/$hemi.cvs.to$templateid.sphere.reg) || $CleanSurfReg) then
    # the spherical registration does not yet exist
    set cmd = (mris_register -1 -dist 1.0 -inflated $movingsurfdir/$hemi.sphere $templatesurfdir/$hemi.sphere $movingsurfdir/$hemi.cvs.to$templateid.sphere.reg)
    echo $cmd >> $LF
    echo $cmd >> $sLF
    $cmd |& tee -a $LF
    if($status) exit 1;
  endif
endif #BothHemis

## Resampling based upon surface-based registration
if ($BothHemis) then
  foreach hemi (lh rh)
    foreach surf (white pial)
      if (!(-e $outdir/$hemi.resample.$surf) || $CleanSurfReg) then 
        set cmd = (mris_resample --atlas_reg $templatesurfdir/$hemi.sphere --annot_in $movinglabeldir/$hemi.$annotfile --annot_out $outdir/$hemi.resample.$annotfile --subject_surf $movingsurfdir/$hemi.$surf --subject_reg $movingsurfdir/$hemi.cvs.to$templateid.sphere.reg --out $outdir/$hemi.resample.$surf)     
        echo $cmd >> $LF
        echo $cmd >> $sLF
        $cmd |& tee -a $LF
        if($status) exit 1;
      endif
    end  # (white, pial)
  end    # (hemi)
else
  foreach surf (white pial)
    if (!(-e $outdir/$hemi.resample.$surf) || $CleanSurfReg) then 
      set cmd = (mris_resample --atlas_reg $templatesurfdir/$hemi.sphere --annot_in $movinglabeldir/$hemi.$annotfile --annot_out $outdir/$hemi.resample.$annotfile --subject_surf $movingsurfdir/$hemi.$surf --subject_reg $movingsurfdir/$hemi.cvs.to$templateid.sphere.reg --out $outdir/$hemi.resample.$surf)     
      echo $cmd >> $LF
      echo $cmd >> $sLF
      $cmd |& tee -a $LF
      if($status) exit 1;
    endif
  end  # (white, pial)
endif #BothHemis

set Step1EndTime = `date +%s`;

@ Step1DiffTime = $Step1EndTime - $Step1StartTime
set tmpTimeMsg = "mri_cvs_register: Step 1 (spherical registration) took $Step1DiffTime seconds"
echo $tmpTimeMsg |& tee -a $sLF
echo $tmpTimeMsg >> $LF

endif # --step1

### REGISTRATION: STEP 2: # CVS_step2.csh
###     elastic registartion

setenv FREESURFER_HOME_BIN $FREESURFER_HOME/bin
setenv VOLTYPE $voltype
setenv ANNOTFILE $annotfile
setenv OUTDIR $outdir 

set mmri = $SUBJECTS_DIR/$movingid/mri/
set tmri = $TEMPLATE_DIR/$templateid/mri/
set tsurf  = $TEMPLATE_DIR/$templateid/surf/
set tlabel = $TEMPLATE_DIR/$templateid/label/

set out_root = el_reg
set elasticmorph = ${out_root}_to$templateid.tm3d

if ($DoAllSteps || $OnlyStep2) then 

echo "Ready for elastic registration (CVS: Step 2)" >> $sLF
set Step2StartTime = `date +%s`;

## Run the elastic registration
###
# Note about the elasticoptions parameters:
# * It is not really the individual values but the ratio of penalty_weight and young that counts. When pw/y 
#   is very very small the moving volume is hardly affected and the output will be the affinely transformed
#   volume (affine matrix computed from the surface-based registration). When that ratio is 1, the alignment
#   is pretty good, but there are some artifacts. For example, the moving brain will not exactly overlap 
#   (size-wise) with the target brain (and that will be corrected during the following steps.
# * pw = 1: gives the affinely moved volume as an output 
# * steps = 1: the output is very fragmented; the diffusion process only begins; does not seem to make too 
#           much of a difference within reasonable interval; higher than about 75 fails
# * poisson ratio: according to the literature should be about .45-.499, but those values result in artifacts;
#                 That is why the current value is established lower. (BTW, .3 or .4 does not seem to make a 
#                 big difference.)
# * newtopology option should not be used
###
if (!(-e $outdir/$elasticmorph) || $CleanElReg) then
 set elasticoptions = (-lin_res 20 -ksp_rtol 1.0e-9 -penalty_weight 1000 -fem_steps 17 -elt_vol_range 5.0,10.0 \
                       -topology_old -compress -pc_type jacobi -ksp_type preonly \
                       -ksp_view -ksp_converged_reason -poisson .3 -young 1000)
 if ($BothHemis) then
  set cmd = (surf2vol -fixed_mri $tmri/$voltype.mgz -moving_mri $mmri/$voltype.mgz  \
                      -fixed_surf $tsurf/lh.white     -moving_surf $outdir/lh.resample.white \
                      -fixed_surf_2 $tsurf/rh.white   -moving_surf_2 $outdir/rh.resample.white \
                      -fixed_surf_3 $tsurf/lh.pial    -moving_surf_3 $outdir/lh.resample.pial \
                      -fixed_surf_4 $tsurf/rh.pial    -moving_surf_4 $outdir/rh.resample.pial \
                      -aparc $tlabel/lh.aparc.annot   -aparc_2 $tlabel/rh.aparc.annot \
                      -aparc_3 $tlabel/lh.aparc.annot -aparc_4 $tlabel/rh.aparc.annot \
                      $elasticoptions -cache_transform $outdir/transform.txt \
                      -out $outdir/${elasticmorph:r}.mgz -out_mesh $outdir/${elasticmorph:r} -out_affine $outdir/${elasticmorph:r}.affine.mgz )
		    # -out_surf $outdir/surf-mfc_to$templateid

  echo $cmd >> $LF
  echo $cmd >> $sLF
  $cmd |& tee -a $LF
  if($status) exit 1;
 else
  set cmd = (surf2vol -fixed_mri $tmri/$voltype.mgz -moving_mri $mmri/$voltype.mgz  \
                      -fixed_surf $tsurf/$hemiReq.white     -moving_surf $outdir/$hemiReq.resample.white \
                      -fixed_surf_2 $tsurf/$hemiReq.pial    -moving_surf_2 $outdir/$hemiReq.resample.pial \
                      -aparc $tlabel/$hemiReq.aparc.annot   -aparc_2 $tlabel/$hemiReq.aparc.annot \
                      $elasticoptions -cache_transform $outdir/transform.txt \
                      -out $outdir/${elasticmorph:r}.mgz -out_mesh $outdir/${elasticmorph:r} -out_affine $outdir/${elasticmorph:r}.affine.mgz)
                      # -out_surf $outdir/surf-mfc_to$templateid \
  
  echo $cmd >> $LF
  echo $cmd >> $sLF
  $cmd |& tee -a $LF
  if($status) exit 1;
 endif
endif

set Step2EndTime = `date +%s`;

@ Step2DiffTime = $Step2EndTime - $Step2StartTime
set tmpTimeMsg = "mri_cvs_register: Step 2 (elastic registration) took $Step2DiffTime seconds"
echo $tmpTimeMsg |& tee -a $sLF
echo $tmpTimeMsg >> $LF

endif #--step2

if ($DoAllSteps || $OnlyStep3) then 

set Step3StartTime = `date +%s`;

## Apply results of elastic registration to aseg 

if ($UseAseg) then 
  set voltype = $asegfname
  if (!(-e $outdir/${elasticmorph:r}_${voltype}.mgz) || $CleanSurfReg) then 
    set cmd = (applyMorph --template $tmri/$voltype.mgz --transform $outdir/${elasticmorph} vol $mmri/$voltype.mgz $outdir/${elasticmorph:r}_${voltype}.mgz nearest)
    echo $cmd >> $LF
    echo $cmd >> $sLF
    $cmd |& tee -a $LF
    if($status) exit 1;
  endif
endif


### REGISTRATION: STEP 3: # CVS_step3.csh
###     intensity-based volumetric registration
###        (UseAseg==0) no aseg registration
###        (UseAseg==1) use aseg registration
###        (UseInt==0)  no intensity-based registration
###        (UseInt==1)  use intensity-based registration
###    default: UseAseg == 1 and UseInt == 1

echo "Ready for volumetric registration (CVS: Step 3)" >> $sLF

if ($UseAseg) then
  set voltype = $asegfname
  set input = ${elasticmorph:r}  # INPUT morph from CVS_step2
  set nl_regresult = nlalign-${voltype}.${morphsuffix}
  # set options = (-passes 3 -z 1 -aseg -dtrans 1 -apply 1 -sigma .25 -fixed -dt 0.25 -m 0.25 -intensity 0.0 -T $cvsdir/id.xfm )
  # set options = (-noneg -1 -passes 3 -z -1 -aseg -dtrans .025 -apply 1 -sigma .25 -intensity 0.0 -fixed -dt 0.25 -m 0.25)
  set options = (-noneg -1 -passes 3 -z -1 -aseg -dtrans .1 -apply 1 -sigma .25 -intensity 0.0 -fixed  -dt 0.25 -m 0.25 -T $cvsdir/id.xfm)
  if !(-e $outdir/${input}_${voltype}.mgz) then 
    echo 'ERROR: What happened? The ' $outdir/${input}_${voltype}.mgz ' file does not exist!'
    exit 1;
  endif
## Run the non-linear registration based on the aseg volumes.
  if (!(-e $outdir/${nl_regresult}) || $CleanVolReg) then
    if ($downsample) then
      set cmd = (mri_nl_align -downsample $downsample $options $outdir/${input}_${voltype}.mgz $tmri/$voltype.mgz $outdir/${nl_regresult})
    else 
      set cmd = (mri_nl_align $options $outdir/${input}_${voltype}.mgz $tmri/$voltype.mgz $outdir/${nl_regresult})
    endif
    echo $cmd >> $LF
    echo $cmd >> $sLF
    $cmd |& tee -a $LF
    if($status) exit 1;
  endif
  
## COMBINE the elastic and aseg nonlinear morphs and APPLY the outcome to the norm volume (for the next registration step)
## CREATE also the m3z version of the combined morph
  set combined = combined_to${templateid}_elreg_$voltype.tm3d  
  if (!(-e $outdir/$combined) || $CleanElReg || $CleanVolReg) then
    set cmd = ( createMorph --out $outdir/$combined --template $tmri/$voltype.mgz \
                            --subject $mmri/$voltype.mgz --in gcam $outdir/${nl_regresult} \
                            morph $outdir/${input}.tm3d )  
    echo $cmd >> $LF
    echo $cmd >> $sLF
    $cmd |& tee -a $LF
    if($status) exit 1;
  endif  

  if (!(-e $outdir/${combined:r}.${morphsuffix}) || $CleanElReg || $CleanVolReg) then
    set cmd = (exportGcam --fixed $tmri/$voltype.mgz --moving $mmri/$voltype.mgz \
                          --morph $outdir/$combined --out_gcam $outdir/${combined:r}.${morphsuffix})			  

    echo $cmd >> $LF
    echo $cmd >> $sLF
    $cmd |& tee -a $LF
    if($status) exit 1;

  endif

  # apply the gcam morph to aseg so  that 1 less interpolation is applied
  set outputfilename = step1_CVSmorphed_to${templateid}_${voltype}.mgz 
  if (!(-e $outdir/$outputfilename) || $CleanElReg || $CleanVolReg) then
    set cmd = ( mri_vol2vol --targ $tmri/$voltype.mgz --m3z $outdir/${combined:r}.${morphsuffix} --noDefM3zPath \
                            --mov $mmri/${voltype}.mgz --o $outdir/$outputfilename \
                            --interp nearest --no-save-reg )
    echo $cmd >> $LF
    echo $cmd >> $sLF
    $cmd |& tee -a $LF
    if($status) exit 1;
  endif

  #if (-e  $outdir/$outputfilename ) then
  #  set cmd = (rm -f $outdir/${nl_regresult:r}.mgz)
  #  echo $cmd >> $LF
  #  echo $cmd >> $sLF
  #  $cmd |& tee -a $LF
  #  if($status) exit 1;
  #endif

  set voltype  = norm
  set outputfilename = step1_CVSmorphed_to${templateid}_${voltype}.mgz 
  if (!(-e $outdir/$outputfilename) || $CleanElReg || $CleanVolReg) then
    set cmd = ( mri_vol2vol --targ $tmri/$voltype.mgz --m3z $outdir/${combined:r}.${morphsuffix} --noDefM3zPath \
                            --mov $mmri/${voltype}.mgz --o $outdir/$outputfilename \
                            --interp trilin --no-save-reg )
    echo $cmd >> $LF
    echo $cmd >> $sLF
    $cmd |& tee -a $LF
    if($status) exit 1;
  endif
  set oldcombined = $combined
  set input = $outputfilename # input from aseg registration
  set basemorph = ${combined}
endif # (aseg registration)

## Intensity-based registration; the default one. 
if ($UseInt) then
set prefix = ()
set voltype = norm
if ($UseAseg) then # otherwise already asigned
  set prefix = afteraseg-
else
  set input = ${elasticmorph:r}.mgz # input from CVS_step2
  set basemorph = $elasticmorph
endif 

if !(-e $outdir/${input} ) then 
  echo 'ERROR: What happened? The ' $outdir/${input} ' file does not exist!'
  exit 1;
endif

if (!(-e $outdir/nlalign-$prefix${voltype}.${morphsuffix}) || $CleanVolReg) then 
  set nl_regresult = nlalign-$prefix${voltype}.${morphsuffix}
  # set options = (-apply 1 -z 1 -sigma 2 -dt 0.0001 -intensity 0.1 -T $cvsdir/id.xfm  )
  set options = (-renormalize 1 -apply 1 -z 1 -sigma 2 -dt 0.0001 -intensity 0.1 -T $cvsdir/id.xfm  )
  if ($downsample) then
    set cmd = (mri_nl_align -downsample $downsample $options $outdir/${input} $tmri/$voltype.mgz $outdir/${nl_regresult})
  else
    set cmd = (mri_nl_align $options $outdir/${input} $tmri/$voltype.mgz $outdir/${nl_regresult})
  endif
  echo $cmd >> $LF
  echo $cmd >> $sLF
  $cmd |& tee -a $LF
  if($status) exit 1;
endif
## COMBINE the el_reg and the aseg morphs and APPLY it to the norm volumes (next registration step)
## CREATE also the m3z version of the combined morph
if (!(-e $outdir/combined_to${templateid}_elreg_$prefix$voltype.tm3d  ) || $CleanElReg || $CleanVolReg) then 
  set combined = combined_to${templateid}_elreg_$prefix$voltype.tm3d  
  set cmd = ( createMorph --out $outdir/$combined --template $tmri/$voltype.mgz \
                          --subject $mmri/$voltype.mgz --in gcam $outdir/${nl_regresult} \
                          morph $outdir/$basemorph ) 
  echo $cmd >> $LF
  echo $cmd >> $sLF
  $cmd |& tee -a $LF
  if($status) exit 1;
endif

if (!(-e $outdir/combined_to${templateid}_elreg_$prefix$voltype.${morphsuffix}  ) || $CleanElReg || $CleanVolReg) then 
  set cmd = (exportGcam --fixed $tmri/$voltype.mgz --moving $mmri/$voltype.mgz \
                        --morph $outdir/$combined --out_gcam $outdir/${combined:r}.${morphsuffix})
  echo $cmd >> $LF
  echo $cmd >> $sLF
  $cmd |& tee -a $LF
  if($status) exit 1;
endif

endif # int-based registration

if ($cleanup) then # deleting tm3d file!
  echo Cleaning up ...
  if ($UseAseg && $UseInt) then
    set filesToDelete = ($outdir/$oldcombined $outdir/$combined)
  else
    if ($UseInt) then 
      set filesToDelete = $outdir/$combined
    endif
  endif
  set cmd = ( rm -f $filesToDelete)
  echo $cmd >> $LF
  echo $cmd >> $sLF
  $cmd |& tee -a $LF
  if($status) exit 1;
endif

## APPLY the morph to the norm and aseg volumes; former will be resampled
## one less time and the latter is just for visualization
set voltype = norm
set finaloutputfilename = final_CVSmorphed_to${templateid}_${voltype}.mgz
if ((-e $outdir/${combined:r}.${morphsuffix}) && (!(-e  $outdir/$finaloutputfilename ) || $CleanElReg || $CleanVolReg)) then 
  set cmd = (mri_vol2vol --targ $tmri/$voltype.mgz --m3z $outdir/${combined:r}.${morphsuffix} --noDefM3zPath \
		       --mov $mmri/${voltype}.mgz --o $outdir/$finaloutputfilename --no-save-reg)
  echo $cmd >> $LF
  echo $cmd >> $sLF
  $cmd |& tee -a $LF
  if($status) exit 1;
endif

#if (-e  $outdir/$finaloutputfilename ) then
#  set cmd = (rm -f $outdir/${nl_regresult:r}.mgz)
#  echo $cmd >> $LF
#  echo $cmd >> $sLF
#  $cmd |& tee -a $LF
#  if($status) exit 1; 
#endif

set oldfinaloutputfilename = $finaloutputfilename
set voltype = $asegfname
set finaloutputfilename = final_CVSmorphed_to${templateid}_${voltype}.mgz
if ((-e $outdir/${combined:r}.${morphsuffix}) && (!(-e  $outdir/$finaloutputfilename ) || $CleanElReg || $CleanVolReg)) then 
#  set cmd = ( applyMorph --template $tmri/$voltype.mgz --transform $outdir/$combined \
#                         vol $mmri/$voltype.mgz $outdir/${combined:r}_${voltype}.mgz nearest )
  set cmd = ( mri_vol2vol  --targ $tmri/$voltype.mgz --m3z $outdir/${combined:r}.${morphsuffix} --noDefM3zPath \
                           --mov $mmri/${voltype}.mgz --o $outdir/$finaloutputfilename \
                           --interp nearest --no-save-reg )
  echo $cmd >> $LF
  echo $cmd >> $sLF
  $cmd |& tee -a $LF
  if($status) exit 1;
endif

set Step3EndTime = `date +%s`;

@ Step3DiffTime = $Step3EndTime - $Step3StartTime
set tmpTimeMsg = "mri_cvs_register: Step 3 (volumetric registration) took $Step3DiffTime seconds"
echo $tmpTimeMsg |& tee -a $sLF
echo $tmpTimeMsg >> $LF

endif #--step3

if ($OnlyStep3 || $DoAllSteps) then

echo "To check results, run:"
echo "freeview -v $outdir/${oldfinaloutputfilename}  $tmri/norm.mgz $outdir/${finaloutputfilename}:colormap=lut $tmri/$asegfname.mgz:colormap=lut"
echo " "

# rename final morph for easier identification
set cmd = (mv $outdir/${combined:r}.${morphsuffix} $outdir/final_CVSmorph_to$templateid.${morphsuffix})
echo $cmd >> $LF
echo $cmd >> $sLF
$cmd |& tee -a $LF
if($status) exit 1;

# delete intermediate files unless specifically wanted
if ($CleanElReg || $CleanVolReg) then 
  set cmd = (rm -f $outdir/step1_CVSmorphed*mgz $outdir/${elasticmorph:r}*.mgz)
  echo $cmd >> $LF
  echo $cmd >> $sLF
  $cmd |& tee -a $LF
  if($status) exit 1;
endif

# unless otherwise indicated by keepallm3z param, deleting partial m3z morph files (too much space requirement!) 
if (!($keepallm3z)) then 
    set cmd = ( rm -f $outdir/nlalign*.${morphsuffix} $outdir/combined*.${morphsuffix})
    echo $cmd >> $LF
    echo $cmd >> $sLF
    $cmd |& tee -a $LF
    if($status) exit 1;
endif

# unless otherwise indicated by keepelreg param, deleting elreg.tm3d file (too much space requirement!) 
if (!($keepelreg)) then 
    set cmd = ( rm -f $outdir/$elasticmorph)
    echo $cmd >> $LF
    echo $cmd >> $sLF
    $cmd |& tee -a $LF
    if($status) exit 1;
endif
endif

# final time keepinng and logging...
set tmpMsg = "Finished with the cvs-registration pipeline."
echo $tmpMsg |& tee -a $sLF
echo $tmpMsg >> $LF
echo " " |& tee -a $sLF
echo " " >> $LF
set tmpTimeMsg = "Started at $StartTime " 
echo $tmpTimeMsg |& tee -a $sLF
echo $tmpTimeMsg >> $LF
set tmpTimeMsg = "Ended   at `date`"
echo $tmpTimeMsg |& tee -a $sLF
echo $tmpTimeMsg >> $LF
echo " " |& tee -a $sLF
echo " " >> $LF
set tmpMsg = "mri_cvs_register Done" 
echo $tmpMsg |& tee -a $sLF
echo $tmpMsg >> $LF
echo " "

# exit
exit 0;

############--------------##################
############--------------##################
parse_args:
set cmdline = ($argv);
while( $#argv != 0 )

  set flag = $argv[1]; shift;

  switch($flag)

    case "--template":
      if ( $#argv < 1) goto arg1err;
      set templateid = $argv[1]; shift;
      breaksw

    case "--mov":
      if ( $#argv < 1) goto arg1err;
      set movingid = $argv[1]; shift;
      breaksw

    case "--outdir":
      if ( $#argv < 1) goto arg1err;
      set outdir = $argv[1]; shift;
      breaksw

    case "--templatedir":
      if ( $#argv < 1) goto arg1err;
      unsetenv $TEMPLATE_DIR
      setenv TEMPLATE_DIR $argv[1]; shift;
      breaksw

    case "--verbose":
      if ( $#argv < 1) goto arg1err;
      set Verbosity = $argv[1]; shift;
      breaksw

    case "--downsample":
      if ( $#argv < 1) goto arg1err;
      set downsample = $argv[1]; shift;
      breaksw

    case "--noaseg":
      set UseAseg = 0;
      breaksw

    case "--asegfname":
      if ( $#argv < 1) goto arg1err;
      set asegfname = $argv[1]; shift;
      # no file extension should remain in the name!
      # set asegfname = $asegfname:r:r  # fails for aseg.noWMHI.mgz
      # This is hacky, but it works
      set asegfname = `basename $asegfname .mgz`;
      set asegfname = `basename $asegfname .mgh`;
      set asegfname = `basename $asegfname .nii`;
      set asegfname = `basename $asegfname .nii.gz`;
      breaksw

    case "--nointensity":
      set UseInt = 0;
      breaksw

    case "--m3d":
      set usem3d = 1;
      breaksw

    case "--nocleanup":
      set cleanup = 0;
      set keepelreg = 1;
      set keepallm3z = 1;
      breaksw

    case "--keepelreg":
      set keepelreg = 1;
      breaksw

    case "--keepallm3z":
      set keepallm3z = 1;
      breaksw

    case "--cleanall":
      set CleanSurfReg = 1;
      set CleanElReg = 1;
      set CleanVolReg = 1;
      breaksw

    case "--cleansurfreg":
      set CleanSurfReg = 1;
      breaksw

    case "--cleanelreg":
      set CleanElReg = 1;
      breaksw

    case "--cleanvolreg":
      set CleanVolReg = 1;
      breaksw

    case "--step1":
      set OnlyStep1 = 1;
      set DoAllSteps = 0;
    breaksw

    case "--step2":
      set OnlyStep2 = 1;
      set DoAllSteps = 0;
    breaksw

    case "--step3":
      set OnlyStep3 = 1;
      set DoAllSteps = 0;
    breaksw

    case "--mni":
      set usingCVSMNItemplate = 1;
    breaksw

    
    case "--hemi":
      if ( $#argv < 1) goto arg1err;
      set hemiReq = $argv[1]; shift;
      set BothHemis = 0;
    breaksw

    case "--openmp":
      if ( $#argv < 1) goto arg1err;
      set openmpN = $argv[1]; shift;
    breaksw

    case "--no-log":
    case "--nolog":
      set nolog = 1;
      breaksw

    case "--debug":
      set verbose = 1;
      set echo = 1;
      breaksw

    default:
      echo ERROR: Flag $flag unrecognized.
      echo $cmdline
      exit 1
      breaksw
  endsw

end

goto parse_args_return;
############--------------##################

############--------------##################
check_params:

  if($#movingid == 0) then
    echo "ERROR: must spec a moving subject id"
    exit 1;
  endif

  if($#templateid == 0) then
    unsetenv $TEMPLATE_DIR
    setenv TEMPLATE_DIR $FREESURFER_HOME/subjects/
    if ($usingCVSMNItemplate) then
      set templateid = $CVSMNItemplate
      echo "Using the CVS template in MNI space as registration target..."
    else
      set templateid = $FStemplate
      echo "Using the CVS template as registration target..."      
    endif
  endif

  if($templateid == $movingid) then
    echo "ERROR: the moving and the template subjects need to be different!"
    exit 1;
  endif

  if($templateid == $FStemplate) then
    set usingFStemplate = 1;
  endif

  if($templateid == $CVSMNItemplate) then
    set usingCVSMNItemplate = 1;
  endif

goto check_params_return;
############--------------##################

############--------------##################
arg1err:
  echo "ERROR: flag $flag requires one argument"
  exit 1
############--------------##################

############--------------##################
arg2err:
  echo "ERROR: flag $flag requires two arguments"
  exit 1
############--------------##################

############--------------##################
usage_exit:

if($PrintHelp) then
  cat $0 | \
    awk 'BEGIN{prt=0}{if(prt) print $0; if($1 == "BEGINHELP") prt = 1 }'
else
  echo "Usage: mri_cvs_register --mov <subj> --template <subj>"
  echo "Help:  mri_cvs_register --help"
endif

exit 1;

#---- Everything below is printed out as part of help -----#
#-- During make install, the output of 'fsPrintHelp mri_cvs_register.help.xml' -- #
#-- is concatenated to this file --#
BEGINHELP
				Help

NAME
	mri_cvs_register

SYNOPSIS
	Combined Volume and Surface Registration

DESCRIPTION
	This program performs subject-to-subject or subject-to-atlas volume 
	registration using the combined volumetric and surface-based (CVS) 
	registration algorithm (Postelnicu-Zollei-Fischl, TMI09). The CVS 
	registration stream consists of 3 steps: (1) surface-based 
	registration, (2) elastic registration and (3) volumetric 
	regsitration. By default, in the current implementation of the script,
	step (3) consists of two steps: (i) registration using aseg volumes 
	and (ii) registration using intensity volumes. This combination of the
	non-linear volumetric registrations proved to be very robust and 
	accurate, but the (i) step could be eliminated if quicker execution 
	time is required by using the "--noaseg" flag. Make sure that SUBJECTS
	_DIR is properly set before calling this script. 

POSITIONAL ARGUMENTS
	None

REQUIRED FLAGGED ARGUMENTS
	--mov subjid
		FreeSurfer subject name as found in $SUBJECTS_DIR. This 
		identifies the subject that is to be moved / registered to the
		target. 

OPTIONAL FLAGGED ARGUMENTS
	--template subjid
		FreeSurfer subject name as found in $SUBJECTS_DIR (or 
		--templatedir). This identifies the subject that is to be kept
		fixed (template). If this argument is missing from the 
		function call, the CVS template is used. 

	--templatedir directory
		This option needs to be used if the template subject's 
		SUBJECTS_DIR directory is different from that of the moving 
		subject. All the relevant FS recon files should be located 
		here. By default, without using this option, this parameter is
		set to be SUBJECTS_DIR. If the --template argument is not 
		specified, so the registration is to the CVS template, this 
		parameter is implicitely set. 

	--mni
		Use the CVS atlas in MNI152 space as a target for registration
		(as opposed to the default CVS template).

	--outdir directory
		Name of the output directory where all the registration 
		results are written. The default is SUBJECTS_DIR/mov/cvs. The 
		final output directory is going to be ~.6G, but make sure that
		there is around double that amount of space available for the 
		computations.

	--asegfname fname
		Name of the segmentation volume that should be used in order 
		to guide the volumetric registration step. The default value 
		is aseg. Note that both the template and the moving subject 
		needs to have this file if you want to use this option. Also, 
		do not use the file extension of the volume that you are 
		including with this flag!

	Partial run of the registration

	--step1
		Only do step 1 (spherical registration).

	--step2
		Only do step 2 (elastic registration).

	--step3
		Only do step 3 (volumetric registration).

	--noaseg
		Do not use aseg volumes in the volumetric registration 
		pipeline (default is 0). Setting this option could shorten 
		significantly the time of registration, however, might also 
		take away from the accuracy of the final results.

	--nointensity
		Do not use the intensity volumes in the volumetric 
		registration pipeline (default is 0). Setting this option 
		could shorten significantly the time of registration. It also 
		indicates that the intensity values are not to be trusted 
		during the registration.

	--hemi
		Run the CVS registration only one of the hemispheres. For 
		example, in case of single hemisphere ex-vivo cases.

	Cleanup Arguments

	--nocleanup
		Do not delete temporary files (default is 0). If this option 
		is set, make sure you have ~2G space in the output directory.

	--keepelreg
		Do not delete elastic registration (default is 0) outcome. If 
		this option is set, make sure ~1G of space is available in the
		output directory.

	--keepallm3z
		Do not delete m3z morph files that are computed during the CVS
		process (default is 0). 

	--cleanall
		Overwrite / recompute all CVS-related morphs that might have 
		been computed prior to the current CVS run (default is 0).

	--cleansurfreg
		Overwrite / recompute CVS-related surface registration morphs 
		that might have been computed prior to the current CVS run 
		(default is 0).

	--cleanelreg
		Overwrite /recompute the CVS-related elastic registration 
		morph that might have been computed prior to the current CVS 
		run (default is 0).

	--cleanvolreg
		Overwrite / recompute CVS-related volumetric morphs that might
		have been computed prior to the current CVS run (default is 
		0).

	Others

	--m3d
		Use m3d instead of m3z in order to represent the registration 
		morphs (and to avoid potential gzip errors).

	--openmp N
		Assign the number of nodes for openmp runs to be N. The 
		default is = 1. Note, with N = 8, you can get a threefold 
		speedup.

	--nolog
		Do not produce a log file (default is 0).

	--version
		Print version and exit.

	--help 
		Print help and exit.

OUTPUTS
	******************************************************************

	(a) Full CVS (with both (i) and (ii))
	final_CVSmorph_toTEMPLATE.m3z (formerly: combined_toTEMPLATE_elreg_
	afteraseg-norm.m3z)
		the final morph that combines correspondences recovered in 
		steps (1), (2), (3) (i) and (3) (ii) 
	final_CVSmorphed_toTEMPLATE_norm.mgz (formerly 
	nlalign-afteraseg-norm.mgz)
		the CVS morphed norm.mgz file; it is the final result of CVS 
		and contains contributions from ALL registration steps 
		(combination of the elatic morph and the two m3z files
	final_CVSmorphed_toTEMPLATE_aseg.mgz (formerly combined_toTEMPLATE_
	elreg_afteraseg-norm_aseg.mgz)
		the CVS morphed aseg.mgz file; it is the final result of CVS 
		and contains contributions from ALL registration steps 
		(combination of the elatic morph and the two m3z files
	step1_CVSmorphed_toTEMPLATE_aseg.mgz (formerly: nlalign-aseg.mgz) 
		a morphed aseg.mgz file; it is the result of CVS up to (i) of 
		step (3) and contains contributions from registration steps of
		the elatic morph and the aseg-based nonlinear registration
	step1_CVSmorphed_toTEMPLATE_norm.mgz (formerly: combined_toTEMPLATE_
	elreg_aseg_norm.mgz) 
		a morphed norm.mgz file; it is the result of CVS up to (i) of 
		step (3) and contains contributions from registration steps of
		the elatic morph and the aseg-based nonlinear registration
	el_reg_toTEMPLATE_aseg.mgz
		the elastic morph applied to aseg.mgz
	el_reg_toTEMPLATE.mgz
		the elastic morph applied to norm.mgz
	! current version does not keep this file any more ! 
	nlalign-afteraseg-norm.m3z
		the morph resulting from (ii) of step (3) (intensity-based 
		non-linear registration); it is NOT combined with the elastic 
		registration morph
	! current version does not keep this file any more ! combined_
	toTEMPLATE_elreg_aseg.m3z
		the morph that combines correspondences recovered in steps 
		(1), (2) and (3) (i)
	! current version does not keep this file any more ! nlalign-aseg.m3z
		the morph resulting from (i) of step (3) (aseg-based 
		non-linear registration); it is NOT combined with the elastic 
		registration morph

	(b) Shorter version of CVS (using only (ii) in step (3) of the 
	algorithm)
	final_CVSmorph_toTEMPLATE.m3z (formerly: combined_toTEMPLATE_elreg_
	norm.m3z)
		The morph that combines correspondences recovered in steps 
		(1), (2) and (3) (ii)
	final_CVSmorphed_toTEMPLATE_norm.mgz (formerly: nlalign-norm.mgz)
		the morphed norm.mgz file; it is the final result of CVS and 
		contains contributions from ALL registration steps 
		(combination of the elatic morph and the above m3z file)
	el_reg_toTEMPLATE.mgz
		the elastic morph applied to norm.mgz
	! current version does not keep this file any more ! nlalign-norm.m3z
		the morph resulting from step(3) (intensity-based non-linear 
		registration); it is NOT combined with the elastic 
		registration morph

	When the "--nocleanup" option is set: three more files will exist, 
	called combined*tm3d and el_reg*tm3d. These files take up a lot of 
	memory so by default are deleted. These files are

	(a)
	combined_toTEMPLATE_elreg_aseg.tm3d
		the morph that combines correspondences recovered in steps 
		(1), (2) and (3) (i)
	combined_toTEMPLATE_elreg_afteraseg-norm.tm3d
		the morph that combines correspondences recovered in steps 
		(1), (2), (3) (i) and (3) (ii)
	el_reg_toTEMPLATE.tm3d
		the elastic morph that combines correspondences recovered in 
		steps (1) and (2). This file takes up a lot of memory so, by 
		default, is deleted. It can only be recreated if the elastic 
		registration step (--step 2) is re-run.

	(b)
	combined_toTEMPLATE_elreg_norm.tm3d
		the morph that combines correspondences recovered in steps 
		(1), (2) and (3) (ii)
	el_reg_toTEMPLATE.tm3d
		the elastic morph that combines correspondences recovered in 
		steps (1) and (2). This file takes up a lot of memory so, by 
		default, is deleted. It can only be recreated if the elastic 
		registration step (--step 2) is re-run.

	If you ran the mri_cvs_registration script with the "--keepelreg" 
	option then you will also see the output morph from the elastic 
	registration step:
	el_reg_toTEMPLATE.tm3d
		the elastic morph that combines correspondences recovered in 
		steps (1) and (2). This file takes up a lot of memory so, by 
		default, is deleted. It can only be recreated if the elastic 
		registration step (--step 2) is re-run.

	The command also produces two log files. These will be created in the 
	output directory with a .log extension and contain the function calls 
	that are initiated by the registration. The one that has a *summary* 
	prefix is easier to read and does not contain all the function 
	outputs. The longer version is to be consulted if looking for more 
	details or explanations for possible errors.

EXAMPLE 1
	Register Subj1 to average CVS space: mri_cvs_register --mov Subj1ID

EXAMPLE 2
	Register Subj1 to average CVS space with outputs written into "myFav" 
	directory: mri_cvs_register --mov Subj1ID --outdir myFav/Subj1ID/cvs

EXAMPLE 3
	Register Subj1 to Subj2: mri_cvs_register --mov Subj1ID --template 
	Subj2ID

EXAMPLE 4
	Register Subj1 to Subj2 where the two subjects have different SUBJECTS
	_DIR's: mri_cvs_register --mov Subj1ID --template Subj2ID 
	--templatedir OTHER_SUBJECTS_DIR

EXAMPLE 5
	If running mri_cvs_register on lanchpad, use "-l 
	nodes=1:ppn=5,vmem=35gb"

EXAMPLE 6
	Some timing estimates from launchpad with the above node settings: 
	 cvs_avg35 (default) template; launchpad: t = 33.955hrs
	 --openmp = 8; cvs_avg35 (default) template; launchpad: t = 11.28hrs
	 cvs_avg35_inMNI152 template; launchpad: t = 21.69hrs
	 --openmp = 8; cvs_avg35_inMNI152template; launchpad: t = 7.66hrs
	 subject template; launchpad: t = 45.48hrs
	 --openmp = 8; subject template; launchpad: t = 15.07hrs
	 

BUGS
	None

REPORTING
	Report bugs to <freesurfer@nmr.mgh.harvard.edu>

REFERENCES
	
	Combined Volumetric and Surface Registration, 
	G.Postelnicu, L.Zollei, B. Fischl.
	IEEE Transactions on Medical Imaging, Vol 28, No. 4, April 2009

SEE ALSO
	mris_register, mri_nl_align, mris_resample, createMorph, applyMorph, 
	exportGcam


