#!/bin/tcsh -f

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

#set version   = "0.0";  set rev_dat   = "Apr 03, 2024"
# + program for making cluster table of ROI overlap, a la Highlight
#   Don't Hide paper
#
set version   = "1.0";  set rev_dat   = "Apr 05, 2024"
# + add help desc, rename some inputs
#
# ----------------------------------------------------------------

set this_prog = "gen_cluster_table"
set prog_abbr = "gen_clust_tab"
#set tpname    = "${this_prog:gas///}"
set here      = $PWD

# ----------------------- set defaults --------------------------

set input_clust = ""               # dset, cluster map
set prefix      = ""

set min_olap_perc = 10             # perc, min overlap for reporting
set tab_type      = olap           # in theory, could have other types
set DO_STRICT     = 0              # only, only report olap > min_olap_perc

set odir    = $here
set opref   = ""

set wdir    = ""

set DO_CLEAN  = 1                  # default: keep working dir

# ------------------- process options, a la rr ----------------------

if ( $#argv == 0 ) goto SHOW_HELP

set ac = 1
while ( $ac <= $#argv )
    # terminal options
    if ( ("$argv[$ac]" == "-h" ) || ("$argv[$ac]" == "-help" )) then
        goto SHOW_HELP
    endif
    if ( "$argv[$ac]" == "-ver" ) then
        goto SHOW_VERSION
    endif

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

    # --------- required

    else if ( "$argv[$ac]" == "-input_clust" ) then
        if ( $ac >= $#argv ) goto FAIL_MISSING_ARG
        @ ac += 1
        set input_clust = "$argv[$ac]"

    else if ( "$argv[$ac]" == "-input_atlas" ) then
        if ( $ac >= $#argv ) goto FAIL_MISSING_ARG
        @ ac += 1
        set ref_atl = "$argv[$ac]"

    else if ( "$argv[$ac]" == "-prefix" ) then
        if ( $ac >= $#argv ) goto FAIL_MISSING_ARG
        @ ac += 1
        set prefix = "$argv[$ac]"
        set opref  = `basename "$argv[$ac]"`
        set odir   = `dirname  "$argv[$ac]"`

    # --------- opt

    else if ( "$argv[$ac]" == "-min_olap_perc" ) then
        if ( $ac >= $#argv ) goto FAIL_MISSING_ARG
        @ ac += 1
        set min_olap_perc = "$argv[$ac]"

    else if ( "$argv[$ac]" == "-strict" ) then
        set DO_STRICT = 1

    else if ( "$argv[$ac]" == "-workdir" ) then
        if ( $ac >= $#argv ) goto FAIL_MISSING_ARG
        @ ac += 1
        set wdir = "$argv[$ac]"

        set tf = `python -c "print('/' in '${wdir}')"`
        if ( "${tf}" == "True" ) then
            echo "** ERROR: '-workdir ..' is a name only, no '/' allowed\n"
            goto BAD_EXIT
        endif

    else if ( "$argv[$ac]" == "-no_clean" ) then
        set DO_CLEAN = 0
        
    else
        echo "\n\n** ERROR: unexpected option #$ac = '$argv[$ac]'\n\n"
        goto BAD_EXIT
        
    endif
    @ ac += 1
end

# =======================================================================
# ======================== ** Verify + setup ** =========================
# =======================================================================

setenv AFNI_WHEREAMI_NO_WARN YES


if ( "${prefix}" == "" ) then
    echo "** ERROR: need to provide output name with '-prefix ..'"
    goto BAD_EXIT
endif

if ( "${input_clust}" == "" ) then
    echo "** ERROR: need to provide input cluster map with '-input_clust ..'"
    goto BAD_EXIT
endif

if ( "${ref_atl}" == "" ) then
    echo "** ERROR: need to provide input atlas with '-input_atlas ..'"
    goto BAD_EXIT
endif

# make workdir name, if nec
if ( "${wdir}" == "" ) then
    set tmp_code = `3dnewid -fun11`  # should be essentially unique hash
    set wdir     = __workdir_${this_prog}_${tmp_code}
endif

# check output directory, use input one if nothing given
if ( ! -e "${odir}" ) then
    echo "++ Making new output directory: $odir"
    \mkdir -p "${odir}"
endif

# make the working directory
if ( ! -e "${odir}/${wdir}" ) then
    echo "++ Making working directory: ${odir}/${wdir}"
    \mkdir -p "${odir}/${wdir}"
else
    echo "+* WARNING:  Somehow found a premade working directory (?):"
    echo "      ${odir}/${wdir}"
endif

# =======================================================================
# =========================== ** Main work ** ===========================
# =======================================================================

echo "++ Make table for: ${tab_type}"

# ----- copy input map and atlas to wdir

set dset_clust = clust_map.nii.gz
set pref_atlas = ref_atlas
set dset_atlas = ${pref_atlas}.nii.gz

3dcalc -a "${input_clust}" -expr 'a' -prefix "${odir}/${wdir}/${dset_clust}"
3dcalc -a "${ref_atl}"     -expr 'a' -prefix "${odir}/${wdir}/${dset_atlas}"

# propagate table/header info
3drefit -copytables "${ref_atl}" "${odir}/${wdir}/${dset_atlas}"
3drefit -cmap INT_CMAP           "${odir}/${wdir}/${dset_atlas}"

# ----- move to wdir, check input properties

cd "${odir}/${wdir}"

set is_labeltable = `3dinfo -is_labeltable "${dset_atlas}"`
set is_atlas      = `3dinfo -is_atlas      "${dset_atlas}"`

# ----- check what info exists in header about atlas/lt

# to lt or atlas
if ( ! ${is_labeltable} && ! ${is_atlas} ) then
    echo "** ERROR: neither labeltable nor atlas_points in the atlas"
    goto BAD_EXIT
endif

# have atlas, no lt
if ( ! ${is_labeltable} ) then
    # create a labeltable from atlas
    adjunct_atlas_points_to_labeltable          \
        -input   "${dset_atlas}"                \
        -add_lt_to_input
endif

# atlasize ref atlas
@MakeLabelTable -atlasize_labeled_dset "${dset_atlas}"

# ----- get list of clust regions

set all_pos  = `3dROIstats -quiet                                     \
                    -mask "3dcalc( -a ${dset_clust} -expr a*step(a)"  \
                    "${dset_clust}"`

set minval = `3dBrickStat -slow -min "${dset_clust}"`
if ( `echo "${minval} < 0" | bc` ) then
    set all_neg = `3dROIstats -quiet                                     \
                        -mask "3dcalc( -a ${dset_clust} -expr a*step(-a)" \
                        "${dset_clust}"`
else
    set all_neg = ( )
endif

# build list of values: 1, 2, 3, ... N, -1, -2, -3, ..., M (can have gaps)
set all_clust = ( )
foreach ii ( `seq 1 1 ${#all_pos}` ) 
    set vvv = ${all_pos[$ii]}
    # add each value to list as an int (should just be chopping of .00000...)
    set all_clust = ( ${all_clust} `echo "scale=0; ${vvv}/1.0" | bc` )
end
foreach ii ( `seq ${#all_neg} -1 1` ) 
    set vvv = ${all_neg[$ii]}
    # add each value to list as an int (should just be chopping of .00000...)
    set all_clust = ( ${all_clust} `echo "scale=0; ${vvv}/1.0" | bc` )
end

set nclust = ${#all_clust}

# ----- start the output file and formatting

cat <<EOF

++ start of table calculation
--------------------------------------------------------------------------
EOF

set ofile  = "${opref}"
printf "" > "${ofile}"
printf "%5s  %5s   %7s   %s\n"                      \
        "Clust" "Nvox" "Overlap"  "ROI location"    \
    |& tee -a "${ofile}"

set tfile  = __tmp_file_olap.txt

# go through the dset, int by int, to parse a bit
foreach ii ( `seq 1 1 ${nclust}` )
    set nn   = ${all_clust[$ii]}
    set nvox = `3dROIstats -nomeanout -quiet -nzvoxels \
                    -mask "clust_map.nii.gz<${nn}>"        \
                    "clust_map.nii.gz"` 

    # whereami, use label 'ref_atlas' to refer to dset
    whereami                                          \
        -omask "clust_map.nii.gz<${nn}>"              \
        -atlas ref_atlas                              \
        | grep --color=never '% overlap with'         \
        > "${tfile}"

    set nrow = `cat "${tfile}" | wc -l`

    set NEED_ONE = 1
    foreach rr ( `seq 1 1 ${nrow}` )
        set line = `cat "${tfile}" | sed -n ${rr}p`
        set perc = `echo "${line}" | awk '{print $1}'`

        set roi = `echo "${line}"                           \
                    | awk -F'% overlap with' '{print $2}'   \
                    | awk -F, '{print $1}'`

        # is this perc above min_olap_perc?
        set is_ge_min = `echo "${perc} >= ${min_olap_perc}" | bc`

        if ( ${NEED_ONE} && ! ${is_ge_min} && $DO_STRICT ) then
            # overlap below min chosen val, AND we will be strict
            # about not showing it
            set fff = `printf "<%2.1f" "${min_olap_perc}"`
            printf "%5d  %5d %8s%%   %s\n"               \
                "${nn}" "${nvox}" "${fff}"  "-"         \
                |& tee -a "${ofile}"
            set NEED_ONE = 0
        else if ( ${NEED_ONE} ) then
            printf "%5d  %5d  %7.1f%%   %s\n"               \
                "${nn}" "${nvox}" "${perc}"  "${roi}"       \
                |& tee -a "${ofile}"
            set NEED_ONE = 0
        else if ( ${is_ge_min} ) then
            printf "%5s  %5s  %7.1f%%   %s\n"               \
                "" "" "${perc}"  "${roi}"                   \
                |& tee -a "${ofile}"
        endif
    end
end

cat <<EOF
--------------------------------------------------------------------------
EOF

# ----- finished with table, so copy the output to final spot
\cp "${opref}" ../.

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

if ( $DO_CLEAN == 1 ) then
    \rm -rf ${odir}/${wdir}
else
    echo "++ NOT removing temporary axialization working dir: ${odir}/${wdir}"
endif

cat <<EOF

++ DONE. See the output:
   ${odir}/${opref}

EOF

goto GOOD_EXIT

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

SHOW_HELP:
cat << EOF
-------------------------------------------------------------------------
Overview ~1~

This is a program to take a cluster dataset and make a table of
overlaps with respect to a given atlas.

This would be useful for reporting more information about cluster
results than, say, peak voxel or middle-voxel tables.  For usage
example, see:

  Highlight Results, Don't Hide Them: Enhance interpretation, reduce
  biases and improve reproducibility. 
  Taylor PA, Reynolds RC, Calhoun V, Gonzalez-Castillo J, Handwerker
  DA, Bandettini PA, Mejia AF, Chen G (2023). Neuroimage 274:120138. 
  https://pubmed.ncbi.nlm.nih.gov/37116766/

This program basically wraps around the useful 'whereami' program.

auth    : PA Taylor (SSCC, NIMH, NIH, USA)
ver     : ${version}
revdate : ${rev_dat}

-------------------------------------------------------------------------
Options ~1~

-input_clust IC    :(req) input dataset: the map of clusters, of which you 
                    want to list out overlaps. Should be a single 3D volume.

-input_atlas IA    :(req) input dataset: the reference atlas, to be used
                    to identify/list overlaps from the cluster input

-prefix      PPP   :(req) output name for the table, so likely should end 
                    with ".txt" or ".dat", for clarity

-min_olap_perc MOP :minimum overlap (as a percentage value) of cluster with
                    a given reference atlas region to be displayed in the 
                    table. That is, if MOP% or more of the cluster overlaps
                    with a given region, then list that region. 
                    (def: ${min_olap_perc})
                    **See Notes, below, for more about this**
                    
-strict            :by default, if no atlas region overlaps with the 
                    '-min_olap_perc ..' threshold value, then the atlas 
                    region with maximum overlap will be displayed still;
                    use this option, however, to strictly apply the threshold,
                    so no ROI would be shown.

-workdir     WWW   :specify the name of the temporary working directory
                    (which is created as a new subdirectory of the output
                    file location---do not include path info here, just a
                    simple name)

-no_clean          :do not remove working directory (def: remove it)

-echo              :very verbose output when running (for troubleshooting)

-help, -h          :display this meager help info

-ver               :display this program version

-------------------------------------------------------------------------
Notes ~1~

Note that the '-min_olap_perc ..' value specifies the fraction of the
*cluster* for displaying in the table. If your cluster is inherently
much, much larger than your atlas regions, this can mean that you
won't see many overlaps reported in the table.  In such a case, you
might want to lower the '-min_olap_perc ..' significantly.

Future work might be to have a different thresholding criterion,
perhaps based on the fraction of the *atlas* region overlap with the
cluster, for reporting.

-------------------------------------------------------------------------
Examples ~1~

1) Basic usage to create a table:
   gen_cluster_table                                  \
        -input_map   Clust_mask+tlrc.HEAD             \
        -input_atlas MNI_Glasser_HCP_v1.0.nii.gz      \
        -prefix      table_cluster_olap_glasser.txt

2) Basic usage to create a table, using a lower overlap fraction cut-off:
   gen_cluster_table                                  \
        -input_map     Clust_mask+tlrc.HEAD           \
        -input_atlas   MNI_Glasser_HCP_v1.0.nii.gz    \
        -min_olap_perc 5                              \
        -prefix        table_cluster_olap _glasser.txt

EOF

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

    goto GOOD_EXIT

SHOW_VERSION:
   echo "version  $version (${rev_dat})"
   goto GOOD_EXIT

FAIL_MISSING_ARG:
    echo "** ERROR: Missing an argument after option flag: '$argv[$ac]'"
    goto BAD_EXIT

BAD_EXIT:
    exit 1

GOOD_EXIT:
    exit 0
