#! /bin/tcsh -f

#
# reg-feat2anat
#
# Registers example func to freesurfer using fsl
#
# Original Author: Doug Greve
# CVS Revision Info:
#    $Author: nicks $
#    $Date: 2007/01/06 00:01:14 $
#    $Revision: 1.14 $
#
# Copyright (C) 2002-2007,
# The General Hospital Corporation (Boston, MA).
# All rights reserved.
#
# Distribution, usage and copying of this software is covered under the
# terms found in the License Agreement file named 'COPYING' found in the
# FreeSurfer source code root directory, and duplicated here:
# https://surfer.nmr.mgh.harvard.edu/fswiki/FreeSurferOpenSourceLicense
#
# General inquiries: freesurfer@nmr.mgh.harvard.edu
# Bug reports: analysis-bugs@nmr.mgh.harvard.edu
#


set VERSION = '$Id: feat2surf,v 1.14 2007/01/06 00:01:14 nicks Exp $'
set FeatDirList = ();
set ProjFrac = ();
set HemiList = (lh rh);
set Surf = white;
set TargetSubj = fsaverage;
set debug = 0;
set DontRun = 0;
set usedev = 0;
set myoutstatsdir = ();
set NoLog = 0;
set fslext = ();
set CopeOnly = 0;

set PrintHelp = 0;

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

# Parse the command-line arguments
goto parse_args;
parse_args_return:

# Check the command-line arguments
goto check_params;
check_params_return:

if($?DEV == 0) set DEV = "";

foreach FeatDir ($FeatDirList)

# Set up a log file
if(! $NoLog) then
  set LF = $FeatDir/reg/freesurfer/feat2surf.log
  echo log file is $LF
  if(-e $LF) mv $LF $LF.bak
else
  set LF = /dev/null
endif
echo FeatDir is $FeatDir | tee -a $LF
date | tee -a $LF
pwd | tee -a $LF
echo $0 | tee -a $LF
echo $cmdargs | tee -a $LF
uname -a | tee -a $LF
echo "setenv SUBJECTS_DIR $SUBJECTS_DIR" | tee -a $LF
echo "subject is $subject" | tee -a $LF

set statsdir = $FeatDir/stats
set reg_anat2exf = $FeatDir/reg/freesurfer/anat2exf.register.dat
if(! -e $reg_anat2exf) then
  echo "ERROR: cannot find $reg_anat2exf"
  echo "Try running reg-feat2anat"
  exit 1
endif
set subject = `cat $reg_anat2exf| head -n 1`;

# Automatically detect the file format
set exfbase = $FeatDir/example_func
if(-e $exfbase.nii.gz) set fslext = nii.gz;
if(-e $exfbase.nii)    set fslext = nii;
if(-e $exfbase.img)    set fslext = img;
if($#fslext == 0) then
  echo "ERROR: cannot determine type of fsl output"
  exit 1;
endif

# Get a list of images to convert
#set nonomatch # This prevents crashing due to file expansion errors
if($CopeOnly) then
  set imglist = (`ls $statsdir/cope*.$fslext $statsdir/varcope*.$fslext`)
  set subjectlist = ($TargetSubj)
else
  set imglist = (`ls $statsdir/*.$fslext`)
  set imglist = ($imglist `ls $imglist $FeatDir/cluster*.$fslext`)
  set imglist = ($imglist `ls $imglist $FeatDir/rendered_thresh*.$fslext`)
  set subjectlist = ($subject $TargetSubj)
endif

set nimg = $#imglist
if($nimg == 0) then
  echo "ERROR: cannot find any .img, .nii, .nii.gz files in $statsdir"| tee -a $LF
  exit 1;
endif
echo "Found $nimg images in $statsdir" | tee -a $LF

@ nthimg = 0
foreach img ($imglist)
   @ nthimg = $nthimg + 1;
   echo $img ---------------------

   # Get the extension
   set ext = $fslext
   set baseimg = `basename $img $ext`

   # Dont know whether these should be conv too
   #if($baseimg == corrections) continue;
   #if($baseimg == threshac1) continue;

   foreach targ ($subjectlist)
     foreach hemi ($HemiList)

       if($targ != $subject) then
         set outext = $fslext
         set reshape = (--reshape)
       else
         set outext = mgh
         set reshape = ()
       endif

       # Only used for testing
       if($#myoutstatsdir == 0) then
         set outstatsdir = $FeatDir/reg_surf-$hemi-$targ/stats
       else
         set outstatsdir = $myoutstatsdir
       endif

       mkdir -p $outstatsdir
       set outimg = $outstatsdir/$baseimg$outext

       set V2S = mri_vol2surf
       if($usedev) set V2S = $DEV/$V2S/$V2S

      set cmd = ($V2S --src $img --srcreg $reg_anat2exf \
                  --trgsubject $targ --hemi $hemi --out $outimg\
                  --surf $Surf $reshape)
       if($#ProjFrac) set cmd = ($cmd --projfrac $ProjFrac)

       echo " " | tee -a $LF
       echo "#@# $baseimg $targ $hemi $nthimg/$nimg ----=====-----=====----" | tee -a $LF
       date      | tee -a $LF
       pwd       | tee -a $LF
       echo $cmd | tee -a $LF
       if(! $DontRun) $cmd  | tee -a $LF
       if($status) then
         echo "ERROR: with $cmd" | tee -a $LF
         pwd
         exit 1;
       endif
       echo " " | tee -a $LF
     end # hemi list
  end # target subject

  @ nthimg = $nthimg + 1;
end # img list

end # FeatDir List

date | tee -a $LF
echo "feat2surf done" | tee -a $LF

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


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

  set flag = $argv[1]; shift;

  switch($flag)

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

    case "--featdirfile":
      if ( $#argv == 0) goto arg1err;
      set FeatFile = $argv[1];
      if(! -e $FeatFile) then
        echo "ERROR: cannot find $FeatFile"
        exit 1;
      endif
      set FeatDirList = ($FeatDirList `cat $FeatFile`); shift;
      breaksw

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

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

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

    case "--hemi":
      if ( $#argv == 0) goto arg1err;
      set HemiList = $argv[1]; shift;
      if($HemiList != lh && $HemiList != rh) then
        echo "--hemi = $HemiList, must be either lh or rh"
        exit 1;
      endif
      breaksw

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

    case "--cope-only":
      set CopeOnly = 1;
      breaksw

    case "--debug":
      set verbose = 1;
      set echo = 1; # turns on terminal echoing
      set debug = 1;
      breaksw

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

    case "--dontrun":
      set DontRun = 1;
      breaksw

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

    default:
      echo "ERROR: flag $flag not recognized"
      exit 1;
      breaksw
  endsw

end

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

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

if($#FeatDirList == 0) then
  echo "ERROR: must specify at least one feat dir"
  exit 1;
endif

foreach FeatDir ($FeatDirList)
  set reg_anat2exf = $FeatDir/reg/freesurfer/anat2exf.register.dat
  if(! -e $reg_anat2exf) then
    echo "ERROR: cannot find $reg_anat2exf. You must run reg-feat2anat first."
    exit 1;
  endif
  if($?SUBJECTS_DIR == 0) then
    echo "ERROR: FreeSurfer environment variable SUBJECTS_DIR not defined"
    exit 1;
  endif
  if(! -e $SUBJECTS_DIR) then
    echo "ERROR: FreeSurfer SUBJECTS_DIR $SUBJECTS_DIR not found"
    exit 1;
  endif

  set subject = `cat $reg_anat2exf| head -n 1`;
  if(! -e $SUBJECTS_DIR/$subject) then
    echo "ERROR: cannot find FreeSurfer subject $subject in $SUBJECTS_DIR"
    exit 1;
  endif

  foreach hemi ($HemiList)
    set surf = $SUBJECTS_DIR/$subject/surf/$hemi.$Surf
    if(! -e $surf) then
      echo "ERROR: cannot find surface $hemi.$Surf in FreeSurfer $SUBJECTS_DIR/$subject/surf"
      exit 1;
    endif
    if($#ProjFrac) then
      set thickness = $SUBJECTS_DIR/$subject/surf/$hemi.thickness
      if(! -e $thickness) then
        echo "ERROR: cannot find surface $thickness in FreeSurfer $SUBJECTS_DIR/$subject/surf"
        exit 1;
      endif
    endif
  end
end # FeatDirList

#if($?FSLOUTPUTTYPE == 0) set FSLOUTPUTTYPE = ANALYZE
#if($FSLOUTPUTTYPE != ANALYZE && $FSLOUTPUTTYPE != NIFTI) then
#  echo "ERROR: FSLOUTPUTTYPE = $FSLOUTPUTTYPE, must be ANALYZE or NIFTI"
#  exit 1;
#endif


endif

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

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

############--------------##################
usage_exit:
  echo ""
  echo "USAGE: feat2surf"
  echo ""
  echo " --feat dir  <--feat dir>  : Feat output directory"
  echo " --featdirfile file : file with a list of feat directories"
  echo ""
  echo "Optional flags and arguments:"
  echo ""
  echo " --projfrac fraction : project fraction into cortical surface (default is 0)"
  echo " --hemi hemi : run on hemi (lh or rh) only. Default is lh and rh. "
  echo " --target subject : subject used to define common surface space (default is fsaverage)"
  echo " --surf surface : surface to resample to (default is white)"
  echo " --cope-only : only map the copes and varcopes to the common surface space"
  echo " "
  echo " --version : print version and exit"
  echo " --help    : print help and exit"
  echo " --debug   : turn on debugging"
  echo " --nolog   : do not create a log file"
  echo " --out outdir : put output in outdir instead of feat/reg_surf-?h/stats (debugging)"
  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

Resamples Feat statistics onto the surface of the subject and onto a
stereo-taxic surface atlas.

Statistics are obtained from FeatDir/stats as well as those volumes in
FeatDir beginning with "cluster" and "rendered". The results are
stored in FeatDir/reg_surf-lh-SUBJECT/stats, and
FeatDir/reg_surf-rh-SUBJECT/stats where SUBJECT is the freesurfer name
of the subject. It will also resample to the common space and stored
the results in in FeatDir/reg_surf-lh-targid/stats and
FeatDir/reg_surf-rh-targid/stats, where targid is the subject that
defines the common surface space (default is fsaverage). If you are using
the "new" FreeSurfer recon where you have registered your surfaces
to the "filled" atlas, then use fsaverage instead.

Works properly on ANALYZE or NIFTI; output is stored in mgz format.

Creates log file featdir/reg/freesurfer/feat2surf.log

REQUIRED ARGUMENTS

--feat featdir <--feat featdir ...>

Directory where Feat results are stored. Can specify multiple --feat.

--featdirfile file <--featdirfile file>

File with a list of Feat directories. Both --feat and --featdirfile
can be specified (multiple times).

OPTIONAL ARGUMENTS

--projfrac fraction

Sample functional a fraction of the cortical thickness normal to the
surface. Eg, --projfrac 0.5 will sample in the middle of the cortical
ribbon. Default is 0.  The subject must have thickness files in the
surf directory.

--hemi hemi

Run on hemi (lh or rh) only. Default is to do both.

--target subject

Subject used to define common surface space (default is fsaverage).

--surf surface

Surface to resample to (default is white).

EXAMPLE

# Assume a data set exists called fbert.img
# Analyze fbert.img with Feat to generate directory fbert.feat

# Register fbert.feat to subject bert:
reg-feat2anat --feat fbert.feat --subject bert

# Resample fbert.feat onto the surface
feat2surf --feat fbert.feat

# View on native surface
tksurfer bert lh inflated \
  -overlay fbert.feat/reg_surf-lh-bert/stats/zstat1.nii.gz

# View on common surface
tksurfer fsaverage lh inflated \
  -overlay fbert.feat/reg_surf-lh-fsaverage/stats/zstat1.nii.gz


BUGS

The surface-based data are stored in "volume" formats (ie, the format
found in the FEAT dir).  In this case, the spatial dimensions do not
correspond to volume dimensions but rather the number of vertices on
the surface. This is typically on the order of 150,000. Ideally, we
would simply store the surface data as a "volume" with 150,000
columns, 1 row, and 1 slice.  However, ANALYZE cannot represent
dimensions over 2^15, or 32768.  Same problem with NIFTI. To get
around this, we factor the number of vertices into dimensions smaller
than 32768. Eg, the fsaverage surface has 163842 vertices which we
factor into 1974x83. However, for individuals there is no guarantee
that the number of vertices will have a factor less than 32768. For
this reason the data resampled on the individual surfaces is stored in
MGH format (which does not have these restrictions).










