#!/usr/bin/tcsh -f

# rca-rcac-prep - uses recon-all-clinical commands to preprocess the
# input for use with recon-all. 

if(-e $FREESURFER_HOME/sources.csh) then
  source $FREESURFER_HOME/sources.csh
endif

set VERSION = '$Id$';
set scriptname = `basename $0`
set PYTHON_SCRIPT_DIR = $FREESURFER_HOME/python/scripts
set MODEL = $FREESURFER_HOME/models/synthsurf_v10_230420.h5

set subject = ();
set ForceUpdate = 0
set RunReconAll = 0;
set threads = 1
set hemilist = ()
set invol = ()
set SkipCCSeg = 0;

set tmpdir = ();
set cleanup = 1;
set LF = ();

set inputargs = ($argv);
set PrintHelp = 0;
if($#argv == 0) goto usage_exit;
set n = `echo $argv | grep -e -help | wc -l` 
if($n != 0) then
  set PrintHelp = 1;
  goto usage_exit;
endif
set n = `echo $argv | grep -e -version | wc -l` 
if($n != 0) then
  echo $VERSION
  exit 0;
endif
goto parse_args;
parse_args_return:
goto check_params;
check_params_return:

set StartTime = `date`;
set tSecStart = `date '+%s'`;
set year  = `date +%Y`
set month = `date +%m`
set day   = `date +%d`
set hour   = `date +%H`
set min    = `date +%M`

mkdir -p $outdir/scripts $rcacdir/transforms
pushd $outdir > /dev/null
set outdir = `pwd`;
popd > /dev/null

if($#tmpdir == 0) then
  if(-dw /scratch)   set tmpdir = /scratch/tmpdir.rca-rcac-prep.$$
  if(! -dw /scratch) set tmpdir = $outdir/tmpdir.rca-rcac-prep.$$
endif
#mkdir -p $tmpdir

# Set up log file
if($#LF == 0) set LF = $outdir/scripts/rca-rcac-prep.Y$year.M$month.D$day.H$hour.M$min.log
if($LF != /dev/null) rm -f $LF
echo "Log file for rca-rcac-prep" >> $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
ls -l $0  | tee -a $LF
echo "" | tee -a $LF
cat $FREESURFER_HOME/build-stamp.txt | tee -a $LF
echo $VERSION | tee -a $LF
uname -a  | tee -a $LF
echo "pid $$" | tee -a $LF
if($?PBS_JOBID) then
  echo "pbsjob $PBS_JOBID"  >> $LF
endif
if($?SLURM_JOB_ID) then
  echo SLURM_JOB_ID $SLURM_JOB_ID >> $LF
endif

#========================================================
# Copy and conform the input
set source = $outdir/mri/source.mgz
if($#invol) then
  # Note: invol will not be set if running on an existing folder
  set ud = `UpdateNeeded $source $invol`
  if($ud || $ForceUpdate) then
    set cmd = (mri_convert  $invol $source -odt float)
    echo $cmd | tee -a $LF
    fs_time $cmd |& tee -a $LF
    if($status) goto error_exit
  endif
endif
set sourceconf = $outdir/mri/source.conf.mgz
set ud = `UpdateNeeded $sourceconf $source`
if($ud || $ForceUpdate) then
  set cmd = (mri_convert --conform $source $sourceconf -odt float --no_scale 1)
  echo $cmd | tee -a $LF
  fs_time $cmd |& tee -a $LF
  if($status) goto error_exit
endif

# SynthSeg with aparc
set synthsegapas = $rcacdir/synthseg.apas.mgz
set ud = `UpdateNeeded $synthsegapas $sourceconf`
if($ud || $ForceUpdate) then
  set cmd = (mri_synthseg --i $source --o $synthsegapas --parc \
    --threads $threads --robust --vol $rcacdir/synthseg.apas.csv \
    --cpu --qc $rcacdir/synthseg.apas.qc.csv)
  echo $cmd | tee -a $LF
  fs_time $cmd |& tee -a $LF
  if($status) goto error_exit
endif

# SynthSR
set synthsr = $rcacdir/synthSR.raw.mgz
set ud = `UpdateNeeded $synthsr $source`
if($ud || $ForceUpdate) then
  set cmd = (mri_synthsr --i $source --o $synthsr --threads $threads --cpu)
  echo $cmd | tee -a $LF
  fs_time $cmd |& tee -a $LF
  if($status) goto error_exit
endif

# SynthSurf. This creates the basic recon-all-clinical output that
# will be used below.
set normrcac = $rcacdir/norm.mgz
set mss =  $PYTHON_SCRIPT_DIR/mri_synth_surf.py
set ud = `UpdateNeeded $normrcac $synthsr $source $synthsegapas`
if($ud || $ForceUpdate) then
  set cmd = (fspython $mss --subject_mri_dir $rcacdir --input_image $source \
    --input_synthseg $synthsegapas --cpu --threads $threads --pad 5 \
    --model_file $MODEL)
  echo $cmd | tee -a $LF
  fs_time $cmd |& tee -a $LF
  if($status) goto error_exit
endif

# The only thing we need from this is norm and wm.seg.
# RCAC outputs 266^3 volumes, so crop them back down to 256^3
set normrcacconf = $rcacdir/norm.conf.mgz
set ud = `UpdateNeeded $normrcacconf $normrcac $sourceconf`
if($ud || $ForceUpdate) then
  set cmd = (mri_convert $normrcac --reslice_like $sourceconf $normrcacconf)
  echo $cmd | tee -a $LF
  fs_time $cmd |& tee -a $LF
  if($status) goto error_exit
endif
set wmsegrcac = $rcacdir/wm.seg.mgz
set wmsegrcacconf = $rcacdir/wm.seg.conf.mgz
set ud = `UpdateNeeded $wmsegrcacconf $wmsegrcac $sourceconf`
if($ud || $ForceUpdate) then
  set cmd = (mri_convert $wmsegrcac --reslice_like $sourceconf $wmsegrcacconf -odt uchar --no_scale 1)
  echo $cmd | tee -a $LF
  fs_time $cmd |& tee -a $LF
  if($status) goto error_exit
endif

pushd $outdir/mri

set vollist = (orig.mgz orig_nu.mgz nu.mgz T1.mgz brainmask.auto.mgz synthstrip.mgz\
  norm.mgz brain.mgz brainmask.mgz antsdn.brain.mgz rawavg.mgz)
foreach vol ($vollist)
  if(! -e $vol) ln -fs rcac/norm.conf.mgz $vol
end
if(! -e wm.seg.mgz) ln -fs rcac/wm.seg.conf.mgz wm.seg.mgz
if(! -e transforms) ln -fs rcac/transforms
if(! -e source.mgz) ln -fs rcac/conf.mgz

# ------------------------------------------------------------------
# Below are commands that would be run by recon-all that prepare
# the output folder so that -autorecon2-wm can be run
# ------------------------------------------------------------------

# Run synthseg on the conformed original source without --parc (but
# with --robust, which recon-all does not use). Could probably convert
# the RCAC synthseg output to replace the aparc with the cortex
# label. Currently running it on the conformed source, but maybe need
# to revisit this.
set synthseg = $outdir/mri/synthseg.rca.mgz
set synthsegcsv = $outdir/stats/synthseg.vol.csv
set ud = `UpdateNeeded $synthseg $sourceconf`
if($ud || $ForceUpdate) then
  set cmd = (mri_synthseg --i $sourceconf --o $synthseg --threads $threads \
    --vol $synthsegcsv --keepgeom --addctab --robust)
  #if(! $UseGPU)  set cmd = ($cmd --cpu)
  echo "\n $cmd \n" |& tee -a $LF
  fs_time $cmd |& tee -a $LF
  if($status) goto error_exit;
  pushd $subjdir/mri 
  if(! -e aseg.auto_noCCseg.mgz) ln -sf synthseg.rca.mgz aseg.auto_noCCseg.mgz
  popd
endif

# Creates aseg.auto 
if(! $SkipCCSeg) then
  set cmd = (seg2cc --s $subject)
  echo "\n $cmd \n" |& tee -a $LF
  fs_time $cmd |& tee -a $LF
  if($status) goto error_exit;
else
  pushd $subjdir/mri 
  if(! -e aseg.auto.mgz) ln -sf aseg.auto_noCCseg.mgz aseg.auto.mgz
  popd
endif

set ud = `UpdateNeeded aseg.presurf.mgz aseg.auto.mgz`
if($ud || $ForceUpdate) then
  set cmd = (cp aseg.auto.mgz aseg.presurf.mgz)
  echo $cmd | tee -a $LF
  $cmd | tee -a $LF
endif

set DoCleanWM = 0
set norm = $outdir/mri/norm.mgz
set wmseg = $outdir/mri/wm.seg.mgz
set wmasegedit = $outdir/mri/wm.asegedit.mgz
set ud = `UpdateNeeded $wmasegedit $wmseg $norm $synthseg`
if($ud || $ForceUpdate) then
  set cmd = (mri_edit_wm_with_aseg)
  if(! $DoCleanWM) set cmd = ($cmd -keep-in)
  #if($SynthSegForSurf) set cmd = ($cmd -wmsa aseg.presurf.mgz) # could use -fill-seg-wm
  set cmd = ($cmd -fill-seg-wm) # no aseg to fill wmsas
  set cmd = ($cmd wm.seg.mgz brain.mgz synthseg.rca.mgz wm.asegedit.mgz)
  echo $cmd | tee -a $LF
  fs_time $cmd |& tee -a $LF
  if($status) goto error_exit
endif

set wm = $outdir/mri/wm.mgz
set ud = `UpdateNeeded $wm $wmasegedit $norm`
if($ud || $ForceUpdate) then
  set cmd = (mri_pretess wm.asegedit.mgz wm norm.mgz wm.mgz)
  echo $cmd | tee -a $LF
  fs_time $cmd |& tee -a $LF
  if($status) goto error_exit
endif

if($RunReconAll) then
  set cmd = (recon-all -s $subject -autorecon2-wm -autorecon3 -threads $threads)
  if($#hemilist == 1) set cmd = ($cmd -hemi $hemilist)
  echo $cmd | tee -a $LF
  fs_time $cmd |& tee -a $LF
  if($status) goto error_exit
endif

#========================================================

# Cleanup
# if($cleanup) rm -rf $tmpdir

# Done
echo " " |& tee -a $LF
set tSecEnd = `date '+%s'`;
@ tSecRun = $tSecEnd - $tSecStart;
set tRunMin = `echo $tSecRun/60|bc -l`
set tRunMin = `printf %5.2f $tRunMin`
set tRunHours = `echo $tSecRun/3600|bc -l`
set tRunHours = `printf %5.2f $tRunHours`
echo "Started at $StartTime " |& tee -a $LF
echo "Ended   at `date`" |& tee -a $LF
echo "Rca-Rcac-Prep-Run-Time-Sec $tSecRun" |& tee -a $LF
echo "Rca-Rcac-Prep-Run-Time-Min $tRunMin" |& tee -a $LF
echo "Rca-Rcac-Prep-Run-Time-Hours $tRunHours" |& tee -a $LF
echo " " |& tee -a $LF
echo "rca-rcac-prep Done" |& tee -a $LF
exit 0

###############################################

############--------------##################
error_exit:
echo "ERROR:"

exit 1;
###############################################

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

  set flag = $argv[1]; shift;
  
  switch($flag)

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

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

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

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

    case "--lh":
      set hemilist = ($hemilist lh);
      breaksw

    case "--rh":
      set hemilist = ($hemilist rh);
      breaksw

    case "--rca":
    case "--recon-all":
    case "--run-recon-all":
     set RunReconAll = 1
     breaksw

    case "--skip-cc":
     set SkipCCSeg = 1
     breaksw
    case "--no-skip-cc":
     set SkipCCSeg = 0
     breaksw

    case "--force":
     set ForceUpdate = 1
     breaksw
    case "--no-force":
     set ForceUpdate = 0
     breaksw

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

    case "--nolog":
    case "--no-log":
      set LF = /dev/null
      breaksw

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

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

    case "--cleanup":
      set cleanup = 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($#subject == 0) then
  echo "ERROR: must spec subject"
  exit 1;
endif

set outdir = $SUBJECTS_DIR/$subject
set subjdir = $outdir
set rcacdir = $outdir/mri/rcac

if($#invol && -e $rcacdir/conf.mgz) then
  echo "ERROR: subject $subject has already been started. Do not pass an input"
  echo " volume or delete the subject and re-run"
  exit 1;
endif
if($#invol == 0 && ! -e $outdir/mri/source.conf.mgz) then
  echo "ERROR: must spec invol"
  exit 1;
endif

if($#hemilist != 1) set hemilist = (lh rh)

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:
  echo ""
  echo "rca-rcac-prep uses recon-all-clinical commands to preprocess the input for use with recon-all."
  echo " --s subject"
  echo " --i invol"
  echo " --threads nthreads"
  echo " --run-recon-all -- run recon-all -s subject -autorecon2-wm -autorecon3 -threads threads"
  echo " --lh, --rh : run recon-all with given hemi"
  echo " --skip-cc : do not segment corpus callosum (good for ex vivo)"
  echo ""

  if(! $PrintHelp) exit 1;
  echo $VERSION
  cat $0 | awk 'BEGIN{prt=0}{if(prt) print $0; if($1 == "BEGINHELP") prt = 1 }'
exit 1;

#---- Everything below here is printed out as part of help -----#
BEGINHELP

This program uses recon-all-clinical commands to preprocess the
input for use with recon-all, eg,

rca-rcac-prep --s subject --i input.mgz --threads 20
recon-all -s subject -autorecon2-wm -autorecon3 -threads 20

Can also add
  -no-fix-ento-wm -no-fix-ga -no-fix-mca-dura -no-fix-acj -no-fix-vsinus

Or you can run 
rca-rcac-prep --s subject --i input.mgz --threads 20 --run-recon-all


rca-rcac-prep can take any contrast. It generates orig.mgz orig_nu.mgz
nu.mgz T1.mgz brainmask.auto.mgz synthstrip.mgz norm.mgz brain.mgz
brainmask.mgz antsdn.brain.mgz wm.seg.mgz rawavg.mgz and taliarach.xfm in
transforms. The input data is conformed and shows up as source.mgz
Note that all other volumes (eg, orig.mgz, nu.mgz, etc) appear as
T1-weighted so they work with the rest of recon-all.

After the recon-all-clinical commands are run, then other FS commands
are run to bring it up to the place where -autorecon2-wm can be run.
Do not run recon-all in a way that it calls commands prior to
autorecon2-wm. Of note, synthseg is run on the conformed input, not
the orig.mgz, because orig.mgz is a synthetic T1.

The results are not idential to recon-all-clinical.sh, but they are
very close.  One of the reasons is that RCAC includes the hipp+amyg as
part of the subcortical mass. By default, recon-all also includes
fixes for entowm, vsinus, mca/dura, and acj, and these will cause
differences too if they are turned on. There may be other places 
where RCAC does something different than recon-all.

There are worries about the surface placement on the synthSR synthetic
T1 as synthSR does have a heavy hand, but it can also remove a bunch
of junk in white matter (could be good for ex vivo).

The original intent of this script was to be able to use
recon-all-clinical to process volumes of arbitrary contrast in a way
that would produce all of the regular recon-all output, take
advantages of changes to recon-all, and also be editable (eg, to be
able to edit the filled.mgz, brain.finalsurfs.manedit.mgz; note that
control points will not do anything; I think aseg edits should work
but not sure). The current recon-all-clinical.sh does not respect
edits.

If you re-run rca-rcac-prep on the same folder, then do not include
the input, eg,
# First run
rca-rcac-prep --s subject --i input.mgz --threads 20
# Second and subsequent runs
rca-rcac-prep --s subject  --threads 20







