#!/bin/tcsh
# @ROI_decluster
# remove small clusters from regions based on fraction or number of voxels

@global_parse `basename $0` "$*" ; if ($status) exit 0

set progname = @ROI_decluster

# --------------------- version history with changes -----------------------
#
set version = "1.00"
#

set dset = ""
set outdir = "roidc"
set nvox_thresh = ""
set frac_thresh = ""
set maskset = ""
set outprefix = "rdc"
set keep_rm_files = ""
set NN = "1"

set here = "$PWD"

# ------------------------ process user options --------------------------
set ac = 1
if ($#argv < 1) then
   goto HELP
endif

while ($ac <= $#argv)
    if ("$argv[$ac]" == "-help" || "$argv[$ac]" == "-h") then
        goto HELP

    else if ("$argv[$ac]" == "-ver") then
        echo $version
        exit 0

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

    else if ("$argv[$ac]" == "-input") then
        set this_opt = "$argv[$ac]"
        @ ac ++
        if ( $ac > $#argv ) then
            echo "** missing parameter for option '${this_opt}'"
            exit 1
        endif
        set dset =  $argv[$ac]
    else if ("$argv[$ac]" == "-mask") then
        set this_opt = "$argv[$ac]"
        @ ac ++
        if ( $ac > $#argv ) then
            echo "** missing parameter for option '${this_opt}'"
            exit 1
        endif
        set maskset =  $argv[$ac]
    else if ("$argv[$ac]" == "-outdir") then
        set this_opt = "$argv[$ac]"
        @ ac ++
        if ( $ac > $#argv ) then
            echo "** missing parameter for option '${this_opt}'"
            exit 1
        endif
        set outdir =  $argv[$ac]
    else if ("$argv[$ac]" == "-nvox_thresh") then
        set this_opt = "$argv[$ac]"
        @ ac ++
        if ( $ac > $#argv ) then
            echo "** missing parameter for option '${this_opt}'"
            exit 1
        endif
        set nvox_thresh =  $argv[$ac]

    else if ("$argv[$ac]" == "-frac_thresh") then
        set this_opt = "$argv[$ac]"
        @ ac ++
        if ( $ac > $#argv ) then
            echo "** missing parameter for option '${this_opt}'"
            exit 1
        endif
        set frac_thresh =  $argv[$ac]

    else if ("$argv[$ac]" == "-prefix") then
        set this_opt = "$argv[$ac]"
        @ ac ++
        if ( $ac > $#argv ) then
            echo "** missing parameter for option '${this_opt}'"
            exit 1
        endif
        set outprefix =  $argv[$ac]

    else if ("$argv[$ac]" == "-NN") then
        set this_opt = "$argv[$ac]"
        @ ac ++
        if ( $ac > $#argv ) then
            echo "** missing parameter for option '${this_opt}'"
            exit 1
        endif
        if ("$argv[$ac]" == "1") then
           # facing neighbors only - default
           set NN = "1"
        else if ("$argv[$ac]" == "2") then
           # >sqrt 2 - 2D diagonal neighbors
           set NN = "2"
        else if ("$argv[$ac]" == "3") then
           # >sqrt 3 - 3D diagonal neighbors
           set NN = "3"
        else
           echo "Only values of 1,2,3 allowed"
           exit 1
        endif
    endif
    
    else if ( "$argv[$ac]" == "-keep_rm_files" ) then
        set keep_rm_files = 1

    else if ( "$argv[$ac]" == "-echo" ) then
        set echo

    # ---------- fin ------------------

    else
        echo "** unknown option $argv[$ac]"
        exit 1
    endif
    @ ac ++
end

# ------------------------- check for required inputs
if ($dset == "") then
    echo "No input dataset provided"
    exit 1
endif

if (("${nvox_thresh}" == "") && "${frac_thresh}" == "") then
    echo "Must select either -nvox_thres or -frac_thresh option"
    exit 1
endif

# set high values for either that is not set
if ("${frac_thresh}" == "") then
   set frac_thresh = 1.0
endif

if ("${nvox_thresh}" == "") then
   set nvox_thresh = 1E38
endif

# ------------------------- make OUTDIR
# We don't allow output directory to be $PWD -- must be a subdir; too
# complicated with copying fnames

\mkdir -p "${outdir}"
cd "${outdir}"
if ( "${PWD}" == "${here}" ) then
    echo "** ERROR: Output directory cannot be same current working dir."
    echo "          Please specify new output directory"
    exit 1
endif
cd -

# copy the datasets into the directory and rename
3dcopy $dset "${outdir}/rdc_in.nii.gz"
# copy any atlas and label tables over
3drefit -copytables $dset "${outdir}/rdc_in.nii.gz"

if ("$maskset" != "") then
   3dcopy $maskset "${outdir}/maskset.nii.gz"
   set maskset = maskset.nii.gz
endif

cd "${outdir}"
set inset = rdc_in.nii.gz

# find min and max regions
set mvals = `3dBrickStat -slow -min -max -non-zero $inset`

\rm rm_roi*.nii.gz
# search each ROI one index at a time
foreach roi (`count_afni -digits 4 $mvals[1] $mvals[2]`)
    set nvox = `3dBrickStat -count -non-zero "${inset}<$roi>"`

    # missing value, skip ahead
    if ("$nvox" == "0") then
       continue
    endif

    # find minimum number of voxels to keep in cluster
    set thresh = `ccalc -int -expr "min($nvox_thresh,${frac_thresh}*$nvox)"`

    3dClusterize                                              \
      -idat 0 -ithr 0                                         \
      -1sided RIGHT_TAIL ${roi}                               \
      -pref_dat rm_roi$roi.nii.gz                             \
      -inset    "${inset}<$roi>"                              \
      -mask     "${inset}<$roi>"                              \
      -NN $NN   -overwrite                                    \
      -clust_nvox  ${thresh} -overwrite
end

# find non-zero values. There shouldn't be any overlap here
3dMean -datum short -overwrite -max -prefix ${outprefix}.nii.gz rm_roi*.nii.gz

# copy any atlas and label tables over to final output
3drefit -cmap INT_CMAP -copytables $inset ${outprefix}.nii.gz

# count how many voxels in starting dataset
set nvoxstart = `3dBrickStat -count -non-zero ${inset}`

# count how many voxels are left
set nvoxremaining = `3dBrickStat -count -non-zero ${outprefix}.nii.gz`

# how many voxels removed
set nvoxremoved = `ccalc -int -expr "$nvoxstart -$nvoxremaining"`

# save record
echo "nvox start::$nvoxstart" > rdc_outs.txt
echo "nvox remaining::$nvoxremaining" >> rdc_outs.txt
echo "nvox removed::$nvoxremoved" >> rdc_outs.txt

cat rdc_outs.txt

if ($keep_rm_files != "") then
   \rm rm_roi*.nii.gz 
endif

exit 0


# ===========================================================================
HELP:

cat << SCRIPT_HELP_STRING

Overview ~1~

Script to remove small clusters or standalone voxels from an ROI/atlas dataset

Usage Example ~1~

    @ROI_decluster                                       \
      -input  mydset.nii.gz                              \
      -outdir myoutdir                                   \
      -fracthresh  0.15                                  \
      -prefix newroi_name                                  

   Note only the input dataset and a threshold are required.

Options ~1~

    -input input_dset   :required input dataset. This dataset should be
                         set of integer values. The program mostly assumes
                         approximate isotropic voxels.

    -outdir outdirname  :directory name for output. All output goes to
                         this directory. Default is roidc.

    -nvox_thresh nn     :number of voxels in a cluster to keep
    -frac_thresh nn     :fraction of voxels in a cluster to keep [0.0-1.0]
                         Both types of threshold can be specified at the same
                         time, in which case, the minimum value would be used.
                         For example, an nvox_thresh of 10 and a frac_thresh
                         of 0.15 would remove all voxels that occupied at least
                         15% of the number of voxels in the region and at least
                         10 voxels.

    -prefix baseprefix  :base name of final output dataset, i.e. baseprefix.nii.gz
                         Default is rdc, so output would be rdc.nii.gz

    -NN [1,2,3]         :neighborhood type using in finding mode, 
                         1 - facing neighbors, 2-edges, 3-corners

Also see these programs with these related functions:
   3dClusterize - reports and extracts clusters (main program called by this one)  
   @ROI_modal_grow - grows regions using non-zero modal smoothing
   3dROImaker - grows regions using regular dilation iteratively

SCRIPT_HELP_STRING

   exit 0
