#!/usr/bin/tcsh -f

#
# bbregister
#
# Original Author: Doug Greve
#
# Copyright © 2021 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 VERSION = 'bbregister mockbuild-local';
set inputargs = ($argv);

set subject = ();
set movvol = ();
set intvol = (); # intermediate volume
set frame = ();
set midframe = 0;
set outreg = ();
set outfsl = ();
set outlta = ();
set InitFSL = 0;
set InitSPM = 0;
set InitCoreg = 1;
set InitRR = 0;
set SPMUseNII = 0;
set InitHeader = 0;
set InitReg = ();
set InitRegOut = ();
set VSM = ();
set VSMReg = (); #reg from VSM space to (distorted) movable space
set pedir = 2
set VSMmul = ()
set Brute1Max = 4;
set Brute1Delta = 4;
set DoBrute2 = 1;
set SubSamp1 = 100;
set DoAbs = 0;
set SaveCurReg = 1;
set featdir = ();
set InitCostFile = ();
set CostFailThresh = ();
set fwhm = ();
set CoRegRefMask = 1;

set LHOnly = 0;
set RHOnly = 0;
set Slope1 = 0.5;
set Slope2 = 0.5;
set Offset2 = 0;
set Contrast = ()
set TolF = 1e-8;
set Tol1D = 1e-3;
set nPowellMax = 36;
set DOF = 6;
set coregDOF = 6;
set FSLDOF = 6;
set FSLSwapTrans = 0;
set FSLBETMov = 0;
set DoPass1 = 1;
set InitSurfCostOnly = 0;

set WMProjAbs = 2;
set GMProjFrac = 0.5;
set GMProjAbs = ();
set IncludeZeroVoxels = 0

set nSubSamp = 1;
set Interp = trilinear
set UseEPIMask = 0;
set UseCortexLabel = 1;

set RMSFile = ();
set RMSFile0 = ();
set templateout = ();
set OutVol = ();
set fsvol  = brainmask;
set initsurfcost = ();
set surfcost = ();
set surfcon  = ();
set surfname = "white";
set MaskLabel = ();
set lhmask = ();
set rhmask = ();
set TargetVol = (); # Full path, instead of SUBJETS_DIR/mri/orig.mgz

set RandInitMax = ();

set debug = 0;
set tmpdir = ();
set cleanup = 1;
set PrintHelp = 0;
set nolog = 0;

set DoInitBest = 0;
set InitBestList = ()

if($?FS_OMP_NUM_THREADS) then
  setenv OMP_NUM_THREADS $FS_OMP_NUM_THREADS 
else
  setenv OMP_NUM_THREADS 1
endif

if($#argv == 0) goto usage_exit;
set n = `echo $argv | egrep -e -version | wc -l`
if($n != 0) then
  echo $VERSION
  exit 0;
endif

source $FREESURFER_HOME/sources.csh

goto parse_args;
parse_args_return:
goto check_params;
check_params_return:

set StartTime = `date`;
set tSecStart = `date '+%s'`;

if($#outreg)   set outdir = `dirname $outreg`;
if(! $#outreg) set outdir = `dirname $initsurfcost`;

if($#tmpdir == 0) set tmpdir = $outdir/tmp.bbregister.$$
mkdir -p $tmpdir
echo tmp $tmpdir

if(! $nolog) then
  set outregdir  = `dirname $outreg`
  set outregbase = `basename $outreg .dat`
  set outregbase = `basename $outregbase .lta`
  set LF = $outregdir/$outregbase.log
  if(-e $LF) mv $LF $LF.old
else
  set LF = /dev/null
endif

echo "Log file is $LF"

echo "Logfile for bbregister" >> $LF
date |& tee -a $LF
echo ""|& tee -a $LF
echo "setenv SUBJECTS_DIR $SUBJECTS_DIR" |& tee -a $LF
echo "cd `pwd`" |& tee -a $LF
echo $0 $inputargs |& tee -a $LF
echo ""|& tee -a $LF
echo $VERSION |& tee -a $LF
uname -a |& tee -a $LF
echo "FREESURFER_HOME $FREESURFER_HOME" |& tee -a $LF

# Loop through init methods
if($DoInitBest) then
  echo "Finding best from init methods $InitBestList" | tee -a $LF
  rm -f $tmpdir/mincost.dat
  foreach init ($InitBestList)
    echo "#I# $init `date`" | tee -a $LF
    set outregbase = `basename $outreg`;
    set regB = $tmpdir/init.$init/$outregbase
    set cmd = (bbregister $inputargs --no-init-best --init-$init --reg $regB --nolog \
      --tmpdir $tmpdir/init.$init/tmp.bbregister)
    echo "$cmd" | tee -a $LF
    $cmd | tee -a $LF
    if($status) exit 1;
    set mincost = `cat $regB.mincost`
    echo "$init $mincost[1]" >> $tmpdir/mincost.dat
  end
  cat $tmpdir/mincost.dat | sort -n -k 2 > $tmpdir/mincost.sort.dat
  set winner = `head -n 1 $tmpdir/mincost.sort.dat | awk '{print $1}'`
  echo "MM mincost $winner -------------------------" | tee -a $LF
  cat $tmpdir/mincost.sort.dat| tee -a $LF
  echo "MM mincost -------------------------" | tee -a $LF
  set cmd = (cp $tmpdir/init.$winner/$outregbase"*" `dirname $outreg`)
  echo $cmd | tee -a $LF
  $cmd |& tee -a $LF
  if($status) exit 1;
  goto final;
  set tSecEnd = `date '+%s'`;
  @ tSecRun = $tSecEnd - $tSecStart;
  echo "" | tee -a $LF
  echo " " |& tee -a $LF
  echo "Started at $StartTime " |& tee -a $LF
  echo "Ended   at `date`" |& tee -a $LF
  echo "BBR-Run-Time-Sec $tSecRun" |& tee -a $LF
  echo " " |& tee -a $LF
  echo "bbregister Done" |& tee -a $LF

  echo "To check results, run:" |& tee -a $LF
  if($#templateout) then
    echo "tkregister2 --mov $templateout --reg $outreg --surf" |& tee -a $LF
  else
    echo "tkregister2 --mov $movvol --reg $outreg --surf" |& tee -a $LF
  endif
  echo " "
  exit 0;
endif

# Create template
if($#templateout) then
  set template = $templateout
else
  # Use mgh here to avoid annoying changes in the way FS converts to
  # nifit creating inconsistencies between v7 and v81 and v82.
  set template = $tmpdir/template.mgh
endif
set cmd = (mri_convert $movvol $template)
if($#frame != 0) set cmd = ($cmd --frame $frame)
if($midframe) set cmd = ($cmd --mid-frame)
echo $cmd | tee -a $LF
$cmd |& tee -a $LF
if($status) exit 1;

if($#fwhm) then
  # This can be done for testing purposes
  echo "Smoothing template by $fwhm" | tee -a $LF
  set cmd = (mri_fwhm --so --fwhm $fwhm --i $template  --o $template)
  echo $cmd | tee -a $LF
  $cmd |& tee -a $LF
  if($status) exit 1;
endif

if($#InitReg == 0) then
  set regvol = $template
  set InitReg = $tmpdir/reg.init.dat
  if($#intvol) then
    set regvol = $intvol
    set InitReg = $tmpdir/reg.intermediate.dat
  endif
  if($InitFSL) then
    set cmd = (fslregister --s $subject --mov $regvol --reg $InitReg \
      --niters 1 --maxangle 90 --tmp $tmpdir/fslregister \
      --dof $FSLDOF --fsvol $fsvol.mgz)
    if($FSLBETMov)   set cmd = ($cmd --betmov)
    if(! $FSLBETMov) set cmd = ($cmd --nobetmov)
    if($FSLSwapTrans) set cmd = ($cmd --allow-swap --trans)
    if($nolog) set cmd = ($cmd --nolog)
    echo $cmd | tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;
  endif
  if($InitSPM) then
    set cmd = (spmregister --s $subject --mov $regvol --reg $InitReg \
      --tmp $tmpdir/spmregister)
    if($nolog) set cmd = ($cmd --nolog)
    if($SPMUseNII) set cmd = ($cmd --nii)
    echo $cmd | tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;
  endif
  if($InitCoreg) then
    set cmd = (mri_coreg --s $subject --mov $regvol --regdat $InitReg \
      --reg $tmpdir/mri_coreg.lta --nthreads $OMP_NUM_THREADS --dof $coregDOF \
      --sep 4 --ftol .0001 --linmintol .01)
    set apas = $SUBJECTS_DIR/$subject/mri/aparc+aseg.mgz
    if($CoRegRefMask == 0 || ! -e $apas) set cmd = ($cmd --no-ref-mask)
    echo $cmd | tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;
  endif
  if($InitRR) then
    set rrlta = $tmpdir/rr.lta
    set cmd = (mri_robust_register --mov $regvol \
     --dst $SUBJECTS_DIR/$subject/mri/$fsvol.mgz \
     --lta $rrlta --cost NMI --nosym);
    echo $cmd | tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;
    set cmd = (tkregister2_cmdl --mov $regvol --s $subject --lta $rrlta --reg $InitReg)
    echo $cmd | tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;
  endif
  if($InitHeader) then
    set cmd = (tkregister2_cmdl --s $subject --mov $regvol \
      --regheader --reg $InitReg --noedit)
    echo $cmd | tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;
  endif
  if($#intvol) then
    # Intermediate volume
    set InitReg0 = $tmpdir/reg.init.dat
    set cmd = (tkregister2_cmdl --s $subject --mov $template \
      --int $intvol $InitReg  --noedit --reg $InitReg0)
    echo $cmd | tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;
    set InitReg = $InitReg0;
  endif
else
  IsLTA --r $InitReg --o $tmpdir/islta.$$ | tee -a $LF
  if($status) exit 1;
  set InitRegIsLTA = `cat $tmpdir/islta.$$`
  if($InitRegIsLTA) then
    echo "Changing from LTA to register.dat" | tee -a $LF
    set InitRegTKR = $tmpdir/init.reg.$$.dat
    set cmd = (lta_convert --inlta $InitReg --outreg $InitRegTKR)
    echo $cmd | tee -a $LF
    $cmd | tee -a $LF
    if($status) exit 1;
    set InitReg = $InitRegTKR;
 endif
endif

if($#InitRegOut) cp $InitReg $InitRegOut

# Multiply the VSM by the given value
if($#VSM && $#VSMmul) then
  set vsmmulvol = $tmpdir/vsm.mul.nii.gz
  set ud = `UpdateNeeded $vsmmulvol $VSM`
  if($ud) then
    set cmd = (mri_concat --mul $VSMmul $VSM --o $vsmmulvol)
    echo $cmd | tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;
  endif
  set VSM = $vsmmulvol
endif

# Pass 1
set Pass1Reg = $tmpdir/bbr.pass1.dat
if($DoPass1) then
  set cmd = (mri_segreg --mov $template --init-reg $InitReg --out-reg $Pass1Reg\
    --subsamp-brute $SubSamp1 --subsamp $SubSamp1 --tol 1e-4 --tol1d 1e-3 \
    --brute -$Brute1Max $Brute1Max $Brute1Delta --surf $surfname);
  if($#subject) set cmd = ($cmd --s $subject) # must be after --init-reg
  if($#GMProjFrac) set cmd = ($cmd --gm-proj-frac $GMProjFrac)
  if($#GMProjAbs)  set cmd = ($cmd --gm-proj-abs  $GMProjAbs)
  if("$Contrast" == "-1") set cmd = ($cmd --wm-gt-gm $Slope1);
  if("$Contrast" == "+1") set cmd = ($cmd --gm-gt-wm $Slope1);
  if($#MaskLabel)  set cmd = ($cmd --label $MaskLabel);
  if($#lhmask)  set cmd = ($cmd --lh-mask $lhmask);
  if($#rhmask)  set cmd = ($cmd --rh-mask $rhmask);
  if($LHOnly) set cmd = ($cmd --lh-only);
  if($RHOnly) set cmd = ($cmd --rh-only);
  if($#initsurfcost) set cmd = ($cmd --init-surf-cost $initsurfcost);
  if($InitSurfCostOnly) set cmd = ($cmd --init-surf-cost-only);
  if($UseEPIMask) set cmd = ($cmd --mask);
  if(! $UseCortexLabel) set cmd = ($cmd --no-cortex-label);
  if($#VSM) set cmd = ($cmd --vsm $VSM $pedir);
  if($#VSMReg) set cmd = ($cmd --vsm-reg $VSMReg)
  if($IncludeZeroVoxels) set cmd = ($cmd --include-zero-voxels)
  if($#TargetVol) set cmd = ($cmd --target-volume $TargetVol)
  if($#RandInitMax) then
    # Only for testing
    set cmd = ($cmd --trans-rand $RandInitMax --rot-rand $RandInitMax);
  endif
  echo $cmd | tee -a $LF
  $cmd |& tee -a $LF
  if($status) exit 1;
  if($InitSurfCostOnly) then
    if($cleanup) rm -r $tmpdir
    echo "InitSurfCostOnly requested, so exiting now" |& tee -a $LF
    echo "bbregister Done" |& tee -a $LF
    exit 0;
  endif
else
  cp $InitReg $Pass1Reg
endif

# Pass 2
set MinCostFile = $outreg.mincost; # This will be the final cost
set ParamFile = $outreg.param; # This will be the final parameters
set cmd = (mri_segreg --mov $template --init-reg $Pass1Reg \
  --out-reg $outreg --interp $Interp \
  --wm-proj-abs $WMProjAbs --tol $TolF --tol1d $Tol1D\
  --c0 $Offset2 --mincost $MinCostFile --dof $DOF \
  --nmax $nPowellMax --param $ParamFile --surf $surfname);
if($DoBrute2) set cmd = ($cmd --brute -0.1 0.1 0.1)
if($SaveCurReg) set cmd = ($cmd --cur-reg $tmpdir/reg.curopt.dat)
if($#GMProjFrac) set cmd = ($cmd --gm-proj-frac $GMProjFrac)
if($#GMProjAbs)  set cmd = ($cmd --gm-proj-abs  $GMProjAbs)
if($#nSubSamp) set cmd = ($cmd --nsub $nSubSamp);
if($#lhmask)  set cmd = ($cmd --lh-mask $lhmask);
if($#rhmask)  set cmd = ($cmd --rh-mask $rhmask);
if($LHOnly) set cmd = ($cmd --lh-only);
if($RHOnly) set cmd = ($cmd --rh-only);
if($UseEPIMask) set cmd = ($cmd --mask);
if(! $UseCortexLabel) set cmd = ($cmd --no-cortex-label);
if($#VSM) set cmd = ($cmd --vsm $VSM $pedir);
if($#VSMReg) set cmd = ($cmd --vsm-reg $VSMReg)
if($#OutVol) set cmd = ($cmd --o $OutVol);
if($#MaskLabel)  set cmd = ($cmd --label $MaskLabel);
if("$Contrast" == "-1") set cmd = ($cmd --wm-gt-gm $Slope2);
if("$Contrast" == "+1") set cmd = ($cmd --gm-gt-wm $Slope2);
if($#initsurfcost && ! $DoPass1)  set cmd = ($cmd --init-surf-cost $initsurfcost);
if($InitSurfCostOnly) set cmd = ($cmd --init-surf-cost-only);
if($#surfcost)  set cmd = ($cmd --surf-cost $surfcost);
if($#surfcon)   set cmd = ($cmd --surf-con  $surfcon);
if($DoAbs) set cmd = ($cmd --penalty-abs)
if($#InitCostFile) set cmd = ($cmd --initcost $InitCostFile);
if($#RMSFile0) set cmd = ($cmd --rms $RMSFile0);
if($IncludeZeroVoxels) set cmd = ($cmd --include-zero-voxels)
if($#TargetVol) set cmd = ($cmd --target-volume $TargetVol)
echo $cmd | tee -a $LF
$cmd |& tee -a $LF
if($status) exit 1;
if($InitSurfCostOnly) then
  if($cleanup) rm -r $tmpdir
  echo "InitSurfCostOnly requested, so exiting now" |& tee -a $LF
  echo "bbregister Done" |& tee -a $LF
  exit 0;
endif

echo "MinCost: `cat $MinCostFile`" | tee -a $LF

# Compute RMS wrt the initial reg (however it was created)
if($#RMSFile) then
  set rmsdat = ();
  if(! $RHOnly) then
    set lhrms = $tmpdir/rh.rms
    set cmd = (mri_surf2surf --reg $InitReg --reg-diff $outreg \
     --sval-xyz white --rms $lhrms --s $subject --hemi lh)
    echo $cmd | tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;
    set rmsdat = (`cat $lhrms`);
  endif
  if(! $LHOnly) then
    set rhrms = $tmpdir/rh.rms
    set cmd = (mri_surf2surf --reg $InitReg --reg-diff $outreg \
     --sval-xyz white --rms $rhrms --s $subject --hemi rh)
    echo $cmd | tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;
    set rmsdat = ($rmsdat `cat $rhrms`);
  endif
  echo $rmsdat > $RMSFile
  echo Final RMS $rmsdat | tee -a $LF
endif

final:

if($#outfsl) then
  set cmd = (tkregister2_cmdl --mov $movvol --reg $outreg \
    --noedit --fslregout $outfsl);
  echo $cmd | tee -a $LF
  $cmd | tee -a $LF
  if($status) exit 1;
endif

if($#outlta) then
  set cmd = (tkregister2_cmdl --mov $movvol --reg $outreg \
    --noedit --ltaout $outlta);
  if($#TargetVol) set cmd = ($cmd --targ $TargetVol)
  echo $cmd | tee -a $LF
  $cmd | tee -a $LF
  if($status) exit 1;
endif

if($#featdir) then
  cp $outreg $featdir/reg/freesurfer/register.dat
  set reg152 = $featdir/reg/freesurfer/anat2std.register.dat
  set cmd = (mni152reg --s $subject --o $reg152)
  echo $cmd | tee -a $LF
  $cmd | tee -a $LF
  if($status) exit 1;
endif

# Cleanup
if($cleanup) then
  echo "Cleaning up" |& tee -a $LF
  rm -r $tmpdir
endif

set tSecEnd = `date '+%s'`;
@ tSecRun = $tSecEnd - $tSecStart;

echo " " |& tee -a $LF
echo "Started at $StartTime " |& tee -a $LF
echo "Ended   at `date`" |& tee -a $LF
echo "BBR-Run-Time-Sec $tSecRun" |& tee -a $LF
echo " " |& tee -a $LF
echo "bbregister Done" |& tee -a $LF

echo "To check results, run:" |& tee -a $LF
set tkrreg = $outreg
if($#outlta) set tkrreg = $outlta
set hemi = ""
if($LHOnly) set hemi = "--lh-only"
if($RHOnly) set hemi = "--rh-only"
if($#templateout) then
  echo "tkregisterfv --mov $templateout --reg $tkrreg --surfs $hemi --sd $SUBJECTS_DIR" |& tee -a $LF
else
  echo "tkregisterfv --mov $movvol --reg $tkrreg --surfs $hemi --sd $SUBJECTS_DIR" |& tee -a $LF
endif
echo " "

if($#CostFailThresh) then
  set FinalCost = `cat  $MinCostFile | awk '{print $1}'`
  set Fail = `echo "$FinalCost > $CostFailThresh" | bc -l`
  if($Fail) then
    echo "ERROR: bbregister ran to completion without error, but the " |& tee -a $LF
    echo "  final cost ($FinalCost) exceed the given threshold ($CostFailThresh)." |& tee -a $LF
    echo "  Manually check the registration. Look for gross misregistrations,"|& tee -a $LF
    echo "  left-right flips, or different subject identities for mov and targ."|& tee -a $LF
    echo "  A gross misregistration probably means the initialization failed."|& tee -a $LF
    echo "  If the registration is ok, rerun with a higher or no threshold."|& tee -a $LF
    echo " "
    exit 1;
  endif
endif

exit 0;
###############################################

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

  set flag = $argv[1]; shift;

  switch($flag)

    case "-h"
    case "-u"
    case "-usage"
    case "--usage"
    case "-help"
    case "--help"
      set PrintHelp = 1;
      goto usage_exit;
      breaksw

    case "--subject":
    case "--s":
      # This should be after --initreg
      if ( $#argv < 1) goto arg1err;
      set subject = $argv[1]; shift;
      breaksw

    case "--feat":
      if ( $#argv < 1) goto arg1err;
      set featdir = $argv[1]; shift;
      if(! -e $featdir) then
        echo "ERROR: cannot find $featdir"
        exit 1;
      endif
      set movvol = `stem2fname $featdir/example_func`
      if($status) then
        echo "$movvol"
        exit 1;
      endif
      mkdir -p $featdir/reg/freesurfer
      if($status) exit 1;
      set outreg = $featdir/reg/freesurfer/anat2exf.register.dat
      set InitFSL = 1;
      set InitSPM = 0;
      set InitHeader = 0;
      set InitReg = ();
      set Contrast = +1;
      breaksw

    case "--s-from-reg":
      if($#argv < 1) goto arg1err;
      set tmp = $argv[1]; shift;
      if(! -e $tmp) then
        echo "ERROR: cannot find $tmp"
        exit 1;
      endif
      #set subject = `head -n 1 $tmp`
      set subject = `reg2subject --r $tmp`;
      breaksw

    case "--mov":
      if ( $#argv < 1) goto arg1err;
      set movvol = $argv[1]; shift;
      if(! -e $movvol) then
        echo "ERROR: cannot find $movvol"
        exit 1;
      endif
      breaksw

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

    case "--int":
      if ( $#argv < 1) goto arg1err;
      set intvol = $argv[1]; shift;
      if(! -e $intvol) then
        echo "ERROR: cannot find $intvol"
        exit 1;
      endif
      breaksw

    case "--vsm":
      if ( $#argv < 1) goto arg1err;
      set VSM = $argv[1]; shift;
      if(! -e $VSM) then
        echo "ERROR: cannot find $VSM"
        exit 1;
      endif
      set UseEPIMask = 1; # Turn on EPI B0 mask by default
      breaksw

    case "--vsm-reg":
      if ( $#argv < 1) goto arg1err;
      set VSMReg = $argv[1]; shift;
      if(! -e $VSMReg) then
        echo "ERROR: cannot find $VSMReg"
        exit 1;
      endif
      breaksw

    case "--vsm-pedir":
      if ( $#argv < 1) goto arg1err;
      set pedir = $argv[1]; shift;
      if($pedir != 1 && $pedir != 2 && $pedir != 3 && \
         $pedir != +1 && $pedir != +2 && $pedir != +3 && \
         $pedir != -1 && $pedir != -2 && $pedir != -3 ) then
        echo "ERROR: pedir = $pedir, must be +/-1, +/-2, or +/-3"
        exit 1;
      endif
      breaksw

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

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

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

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

    case "--fsl-swap-trans":
      set FSLSwapTrans = 1;
      breaksw

    case "--init-coreg":
      set InitFSL = 0;
      set InitSPM = 0;
      set InitCoreg = 1;
      set InitRR = 0;
      set InitHeader = 0;
      set InitReg = ();
      breaksw
 
    case "--init-rr":
      set InitFSL = 0;
      set InitSPM = 0;
      set InitCoreg = 0;
      set InitRR = 1;
      set InitHeader = 0;
      set InitReg = ();
      breaksw
 
    case "--init-fsl":
      set InitFSL = 1;
      set InitSPM = 0;
      set InitCoreg = 0;
      set InitRR = 0;
      set InitHeader = 0;
      set InitReg = ();
      breaksw
 
    case "--init-spm":
      set InitFSL = 0;
      set InitSPM = 1;
      set InitCoreg = 0;
      set InitRR = 0;
      set InitHeader = 0;
      set InitReg = ();
      breaksw
 
    case "--spm-nii":
      set SPMUseNII = 1;
      breaksw
 
    case "--regheader":
    case "--reg-header":
    case "--init-header":
      set InitFSL = 0;
      set InitSPM = 0;
      set InitCoreg = 0;
      set InitHeader = 1;
      set InitReg = ();
      breaksw
 
    case "--init-reg":
      if ( $#argv < 1) goto arg1err;
      set InitReg = $argv[1]; shift;
      if(! -e $InitReg) then
        echo "ERROR: cannot find $InitReg"
        exit 1;
      endif
      set subject = `reg2subject --r $InitReg`
      set InitFSL = 0;
      set InitSPM = 0;
      set InitCoreg = 0;
      set InitHeader = 0;
      breaksw

    case "--no-coreg-ref-mask":
      set CoRegRefMask = 0;
      breaksw
    case "--coreg-ref-mask":
      set CoRegRefMask = 1;
      breaksw

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

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

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

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

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

    case "--abs":
      # Experimental
      set Contrast = +1;
      set DoAbs = 1;
      breaksw

    case "--bold":
    case "--dti":
    case "--T2":
    case "--t2":
      set Contrast = +1;
      breaksw

    case "--T1":
    case "--t1":
      set Contrast = -1;
      breaksw

    case "--s-from-reg":
      if ( $#argv < 1) goto arg1err;
      set tmpfile = $argv[1]; shift;
      set subject = `head -n 1 $tmpfile`;
      if($status) then
        echo "$subject"
        exit 1;
      endif
      breaksw

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

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

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

    case "--mid-frame":
      set midframe = 1;
      breaksw

    case "--target-volume"
      # Full path, instead of SUBJETS_DIR/mri/orig.mgz
      set TargetVol = $argv[1]; shift;
      breaksw

    case "--lh-only":
      set LHOnly = 1;
      set RHOnly = 0;
      breaksw

    case "--rh-only":
      set LHOnly = 0;
      set RHOnly = 1;
      breaksw

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

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

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

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

    case "--no-brute2":
      set DoBrute2 = 0;
      breaksw

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

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

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

    case "--init-surf-cost-only":
      set InitSurfCostOnly = 1;
      set nolog = 1;
      breaksw

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

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

    case "--include-zero-voxels":
      set IncludeZeroVoxels = 1
      breaksw
    case "--no-include-zero-voxels":
      set IncludeZeroVoxels = 1
      breaksw

    case "--tol":
      if ( $#argv < 1) goto arg1err;
      set Tol = $argv[1]; shift;
      set TolF = $Tol
      # set Tol1D = $Tol; only set tolf!
      breaksw

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

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

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

    case "--gm-proj-frac":
      if($#argv < 1) goto arg1err;
      set GMProjFrac = $argv[1]; shift;
      set GMProjAbs = ();
      breaksw

    case "--gm-proj-abs":
      if($#argv < 1) goto arg1err;
      set GMProjAbs = $argv[1]; shift;
      set GMProjFrac = ();
      breaksw

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

    case "--proj-abs":
      if($#argv < 1) goto arg1err;
      set ProjAbs = $argv[1]; shift;
      set WMProjAbs = $ProjAbs;
      set GMProjAbs = $ProjAbs;
      set GMProjFrac = ();
      breaksw

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

    case "--6":
      # Default anyway
      set DOF = 6;
      set coregDOF = 6;
      breaksw

    case "--9":
      set DOF = 9;
      set coregDOF = 9;
      breaksw

    case "--12":
      set DOF = 12;
      set coregDOF = 12;
      breaksw

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

    case "--no-pass1":
      set DoPass1 = 0;
      breaksw

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

    case "--fsl-bet-mov":
      set FSLBETMov = 1;
      breaksw
    case "--no-fsl-bet-mov":
      set FSLBETMov = 0;
      breaksw

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

    case "--rms0":
      # only works with --no-pass1
      if($#argv < 1) goto arg1err;
      set RMSFile0 = $argv[1]; shift;
      breaksw

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

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

    case "--nearest":
      set Interp = nearest
      breaksw

    case "--trilin":
    case "--trilinear":
      set Interp = trilinear
      breaksw

    case "--label":
      if($#argv < 1) goto arg1err;
      set MaskLabel = $argv[1]; shift;
      if(! -e $MaskLabel) then
        echo "ERROR: cannot find $MaskLabel"
        exit 1;
      endif
      breaksw

    case "--mask":
      if($#argv < 2) goto arg2err;
      set lhmask = $argv[1]; shift;
      set rhmask = $argv[1]; shift;
      if(! -e $lhmask) then
        echo "ERROR: cannot find $lhmask"
        exit 1;
      endif
      if(! -e $rhmask) then
        echo "ERROR: cannot find $rhmask"
        exit 1;
      endif
      breaksw

    case "--epi-mask":
      set UseEPIMask = 1;
      breaksw
    case "--no-epi-mask":
      set UseEPIMask = 0;
      breaksw

    case "--no-cortex-label":
      set UseCortexLabel = 0;
      breaksw

    case "--no-save-cur-reg":
      set SaveCurReg = 0;
      breaksw

    case "--init-best":
      set DoInitBest = 1;
      set InitFSL = 0;
      set InitSPM = 0;
      set InitCoreg = 0;
      set InitRR = 0;
      set InitHeader = 0;
      set InitReg = ();
      breaksw
    case "--no-init-best":
      set DoInitBest = 0;
      breaksw
    case "--init-best-fsl":
      set InitBestList = ($InitBestList fsl); 
      #set DoInitBest = 1; Do not do this!
      breaksw
    case "--init-best-spm":
      set InitBestList = ($InitBestList spm); 
      breaksw
    case "--init-best-header":
      set InitBestList = ($InitBestList header); 
      breaksw
    case "--init-best-rr":
      set InitBestList = ($InitBestList rr); 
      breaksw
    case "--init-best-coreg":
      set InitBestList = ($InitBestList coreg); 
      breaksw

    case "--threads"
    case "--nthreads"
      if($#argv < 1) goto arg1err;
      set nthreads = $argv[1]; shift;
      setenv OMP_NUM_THREADS $nthreads
      setenv FS_OMP_NUM_THREADS $nthreads
      breaksw

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

    case "--nocleanup":
    case "--no-cleanup":
      set cleanup = 0;
      breaksw

    case "--cleanup":
    case "--clean-up":
      set cleanup = 1;
      breaksw

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

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

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

end

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

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

  if($#subject == 0) then
    echo "ERROR: must spec a subject id"
    exit 1;
  endif
  if(! -e $SUBJECTS_DIR/$subject && $#TargetVol == 0) then
    # Adding this stuff about the TargetVol is a bit of a hack
    echo "ERROR: cannot find $subject in $SUBJECTS_DIR"
    exit 1;
  endif

  if($#movvol == 0) then
    echo "ERROR: must spec an movput vol"
    exit 1;
  endif

  if($#Contrast == 0) then
    echo "ERROR: you must specify a contrast."
    echo " use --bold, --dti, --t2, or --t1,"
    echo " which ever is most appropriate"
    exit 1;
  endif

  if($InitSurfCostOnly && $#initsurfcost == 0) then
    echo "ERROR: must supply --init-surf-cost with --init-surf-cost-only"
    exit 1;
  endif

  # Check whether output registration file is really lta format
  if($#outreg != 0 && $#outlta == 0) then
    set tmp1 = `basename $outreg `
    set tmp2 = `basename $outreg .lta`
    if("$tmp1" != "$tmp2") then
      set outlta = $outreg
      set outreg = ()
    endif
  endif

  if($#outreg == 0 && ! $InitSurfCostOnly) then
    if ($#outlta == 0) then
      echo "ERROR: must spec an output reg file (using either --reg or --lta)"
      exit 1;
    else
      set outreg = ${outlta:r}.dat
    endif
  endif

  if($#frame && $midframe) then
    echo "ERROR: cannot --frame AND --mid-frame"
    exit 1;
  endif

  if(! $DoInitBest) then
    if(! $InitFSL && ! $InitSPM && ! $InitCoreg && ! $InitRR && ! $InitHeader && ! $#InitReg) then
      echo "ERROR: must spec an init method"
      exit 1;
    endif
  else
    if($InitFSL || $InitSPM ||  $InitCoreg || $InitRR || $InitHeader || $#InitReg) then
      echo "ERROR: cannot spec an init method with --init-best"
      exit 1;
    endif
    if($#InitBestList == 0) set InitBestList = (fsl spm coreg rr header)
    if($#InitBestList == 1) then
      echo "ERROR: must use more than one init method with --init-best"
      exit 1;
    endif
  endif

  if($?BBR_TEST_TOLERANCE) then
    # This allows a program at a much higher level to set the tolerances.
    # This is useful in the case where only the execution needs to be
    # tested (and the output itself is not important). Setting the tolerances
    # to be high makes BBR run faster.
    set TolF  = $BBR_TEST_TOLERANCE
    set Tol1D = $BBR_TEST_TOLERANCE
    echo ""
    echo "WARNING: using BBR_TEST_TOLERANCE $BBR_TEST_TOLERANCE"
    echo ""
    sleep 2
  endif

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: bbregister --s <subj> --mov <volid> --reg <regfile> --<contrast>"
  echo "Help:  bbregister --help"
endif

exit 1;

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