##############################################################################
# annot2roi.tcl (tksurfer): convert fsaverage annot -> subj-specific 2D/3D ROIs
##############################################################################
### Overview
# This script resamples MGH style surface region annotations files
# (*.annot) and can then generate 3D ROIs from them, for either a
# single-subject scan or for fsaverage.
# 
# The primary input is an MGH-style annotation file on the fsaverage
# subject, selected from the dropdown in $SUBJECTS_DIR/fsaverage/labels.
# 
# The first step (skipped if subject is fsaverage) is to sample the
# fsaverage annotation onto an individual subject's surface using
# mri_surf2surf.  The resampled annotation is saved in the subject's
# "label" subdirectory in $SUBJECTS_DIR.
# 
# The second, optional step is to generate AFNI BRIKs containing 3D
# ROIs for each region in the annotation at the resolution of the
# current individual subject functional scan (and aligned with it),
# along with an all-regions-in-one ROI BRIK.  These signed short
# (2-byte) BRIKs will contain the sequential integer region id numbers
# taken from the annotation, which can also be found in the corresponding
# ASCII file in: $SUBJECTS_DIR/fsaverage/scripts/<annotation_infix>.ctab
# When the subject is fsaverage, the ROIs will be generated at 256^3,
# 1mm^3 resolution of the $SUBJECTS_DIR/fsaverage/mri/orig.mgz file.
# 
# The ROI BRIK files are saved to the current functional scan dir for
# single subjects, and to a pseudo functional scandir for fsaverage.
# For fsaverage 3D ROIs, first use csurf -> File -> New Functional
# to create an empty 'functional' session in $FUNCTIONALS_DIR named
# "fsaverage-3D-ROIs" before running the script.
# 
# For an individual subject, two additional required inputs are a
# functional scan (in order to determine ROI BRIK voxel size) and a
# register.dat file (to align the data to the individual subject's
# surface annotation).  If used interactively, select the scan from
# the "scandir:" dropdown in csurf before starting tksurfer.
# 
# For fsaverage, the ROI BRIKs will be generated at the 256^3 1mm^3
# resolution of the $SUBJECTS_DIR/fsaverage/mri/orig.mgz file,
# 
# Other sub-options for the second ROI-making step are to search along
# the surface normal (in either mm or fraction of distance to local
# pial surface).  Any functional voxel (or fsaverage 1mm^3 pseudo
# functional voxel) intersected by the normal search will be included
# in the 3D ROI.  Region boundaries can also be optionally eroded to
# make more focal ROIs.
# 
# Another sub-option is to fill any remaining holes, which can be
# generated when searches continue above the pial surface (e.g., where
# surface normals can diverge on gyral crowns).
# 
# Finally, if both hemispheres have been processed, the left and
# right hemisphere ROI BRIKs will automatically be merged into a BRIK
# without an lh- or rh- prefix (lh idnums first, rh idnums second/higher).
# 
# If subject is fsaverage, the left/right merged all-in-one ROIs BRIK
# will be auto-converted to an MGH compatible (single-hemisphere)
# parcellation file in the fsaverage mri subdir:
# $SUBJECTS_DIR/fsaverage/mri/<annotation_infix>.mgz
#
# For more details, R-click the interactive annot2roi.tcl popup.

### Run from interactive pop-up or as tksurfer cmdline tcl script
# output: $hemi-{ROI_1, ROI_2, ...}-<sampledepth>+orig.BRIK  # each separate
# output: $hemi-ALL_ANNOT_ROIs-<sampledepth>+orig.BRIK       # plus all-in-one

### Def pseudo funct session/scandir (just for fsaverage, no need to change)
set fsaveragefunctdir fsaverage-3D-ROIs ;# pseudofunct sess for fsaverage ROIs
set fsaveragescandir 1-pseudofunct      ;# pseudofunct scandir for inside above

### Def tcl-only on 1st entry (don't biff set-by-popup on interactive reenter)
# don't change these here: for custom script, uncomment/adjust copies below
if ![info exists userok]           { set userok 0 }
if ![info exists erodesteps]       { set erodesteps 0 }
if ![info exists fill3Dholesflag]  { set fill3Dholesflag 1 }
if ![info exists neighfracthresh]  { set neighfracthresh 0.8 }
if ![info exists annotinfix]       { set annotinfix CsurfMaps1 } ;#was HCP-MMP1
if ![info exists make_3D_AFNI_ROIs_flag] { set make_3D_AFNI_ROIs_flag 0 }
#N.B.: tksurfer retains state of these variables after script done
#        except make_3D_AFNI_ROIs_flag forced on if subject fsaverage

### HOWTO: run interactively from tksurfer
#  select annot2roi.tcl from "tcl:" dropdown (under DEFAULT LIB SCRIPTS)
#  GO
#  adjust parms in pop-up
#  RUN SCRIPT
#
### HOWTO: run interactively from tksurfer with saved non-default parms
#  copy this lib script into subject/session scripts dir
#  uncomment/edit parameters below (N.B.: uncommented vars override popup vals!)
#  open inflated surface using csurf SURFACE button (or tksurfer cmdline)
#  find renamed script in "tcl:" dropdown (under LOCAL SUBJECT/FUNCT SCRIPTS)
#  GO
#  verify non-default parms in pop-up (N.B.: addt'l changes in pop-up ignored!)
#  RUN SCRIPT
#
### HOWTO: run from shell/cmdline (no pop-up, no OpenGL surf display window)
#  copy this default lib script into a subject/session scripts dir
#  uncomment/adjust parameters below
#  example (annotinfix=Retintopic-Areas, session=140430MSa, scandir=rawavg):
#    cd $FUNCTIONALS_DIR/140430MSa/image/rawavg-all/scripts
#    tksurfer marser-qT1 rh inflated -tcl annot2roi.tcl
#

##############################################################################
# for cmdline or subj-specific tksurfer tcl script: uncomment/adj these parms
##############################################################################
### N.B.: any vars uncommented here override interactively entered popup values

### set tcl-only parameters (not linked to tksurfer C-variables)
#set erodesteps 0             ;# erode annot before samp->3D, set for standalone
#set fill3Dholesflag 1        ;# pial surface holes, set for standalone
#set neighfracthresh 0.8      ;# (0-1) threshold num neighbors to fill 3D hole
#set annotinfix CsurfMaps1    ;# was HCP-MMP1.annot, set for standalone
#set make_3D_AFNI_ROIs_flag 0 ;# else exit after just mri_surf2surf resample

### set tcl-variables linked to C-variables in tksurfer.c
# for complete list, see: tksurfer -help
### isession autoset to $cwd/.. if cwd="scripts" (set if cmdline elsewhere)
#set isession $env(FUNCTIONALS_DIR)/140430MSa/image
#set scandir 1-polletdilima1         ;# set scandir
#set rawdata */$scandir/polletdilima1-1-vreg+orig.BRIK ;# '*' is isession abbrev
#set regdat */$scandir/register.dat                    ;# surfxyz -> voxindices
### sampling-along-cortical-normal controls
#set normdsampsearchflag 1           ;# turn on search along surface normal
#set normdfracflag  1                ;# use fractional distances instead of mm
#set normdsamp 0.0                   ;# mm search begin
#set normdmax  2.0                   ;# mm search end (same OK)
#set normdfracsamp 0.0               ;# fraction of thickness search begin
#set normdfracmax  0.8               ;# fraction thickness search end (same OK)
##############################################################################

### before panel1: fsavg: force make missing pseudofunct sess: fsaverage-3D-ROIs
if [string match fsaverage $subject] {
  if [file exists $env(FUNCTIONALS_DIR)/$fsaveragefunctdir/image] {
    # silently catch/correct forgot to select already there
    if ![string match */$fsaveragefunctdir/image $isession] {
      puts "tksurfer: [file tail $script]:\
            changing to fsaverage pseudo funct sesssion \"$fsaveragefunctdir\""
      set isession $env(FUNCTIONALS_DIR)/$fsaveragefunctdir/image
    }
  } else {  ;# force make w/csurf (vs. one-of-a-kind  make here)
    puts "tksurfer: [file tail $script]:\
          ### functional sesssion \"$fsaveragefunctdir\" not found"
    puts "tksurfer: [file tail $script]:\
          ### first make that fsaverage funct session in csurf, and try again"
    if [winfo viewable .] {  ;# tcl tools window
      confirmalert "Making 3D ROIs from annotation for fsaverage:\
               \n\nfsaverage pseudofunct session for ROI BRIKs:\
               \n\n    $fsaveragefunctdir\
               \n\ndoesn't exist\
               \n\nKill tksurfer, use csurf -> File -> New Functional\
                 \nto make \"$fsaveragefunctdir\", restart tksurfer,\
                 \nand try annot2roi.tcl again"
      return
    } else { exit }  ;# cmdline script
  }
}

### before panel2: fsavg: auto-mk missing pseudoscandir/pseudofunct/pseudoregdat
if [string match fsaverage $subject] {
  # mk one standard scandir if not there
  set pseudofunctdir $isession/$fsaveragescandir
  if ![file exists $pseudofunctdir] {
    puts "tksurfer: [file tail $script]: make pseudofunct scandir:"
    puts "tksurfer: [file tail $script]:  mkdir $isession/$pseudofunctdir"
    confirmalert "make pseudofunct scandir:\
              \n\n    mkdir $pseudofunctdir"
    set ret [catch { exec mkdir "$pseudofunctdir" } err]
    if {$ret != 0} {
      puts "tksurfer: [file tail $script]: ### mkdir $pseudofunctdir err: $err"
      if [winfo viewable .] {  ;# tcl tools window
        confirmalert "error from \"mkdir $pseudofunctdir\"\n\n    $err"
        unset pseudofunctdir
        return
      } else { exit }  ;# cmdline script
    }
  } else {
    puts "tksurfer: [file tail $script]: $pseudofunctdir scandir already made"
  }
  # mk orig+orig.BRIK if not in standard scandir
  set pseudorawdata $isession/$fsaveragescandir/orig+orig.BRIK ;#$scandir stale
  if ![file exists $pseudorawdata] {
    set cmd \
      "cor2brik   $env(SUBJECTS_DIR)/fsaverage/mri/orig.mgz   $pseudorawdata"
    puts "tksurfer: [file tail $script]: make pseudofunct scan orig+orig.BRIK:"
    puts "tksurfer: [file tail $script]:  $cmd"
    confirmalert "make pseudofunct scan orig+orig.BRIK in:\
              \n\n$pseudofunctdir\
                \nusing cmd:\
              \n\n    $cmd"
    catch { puts [eval exec $cmd] } ret
    if {$ret != ""} {
      puts "tksurfer: [file tail $script]: ### make $pseudorawdata err: $err"
      if [winfo viewable .] {  ;# tcl tools window
        confirmalert "error from \"make $pseudorawdata\"\n\n    $err"
        unset pseudorawdata
        return
      } else { exit }  ;# cmdline script
    }
  } else {
   puts "tksurfer: [file tail $script]: pseudofunct orig+orig.BRIK already made"
  }
  unset pseudorawdata
  # mk fsaverage regdat idmat if not there
  set pseudoregdat $isession/$fsaveragescandir/register.dat
  if ![file exists $pseudoregdat] {
    puts "tksurfer: [file tail $script]: make IDmat regdat for orig+orig.BRIK"
    confirmalert "make IDmat regdat for orig+orig.BRIK:\n\n$pseudoregdat"
    set id [open $pseudoregdat w 0644]
    puts $id "fsaverage"
    puts $id "1.000000"
    puts $id "1.000000"
    puts $id "1.000000"
    puts $id " 1.000000e+00  0.000000e+00  0.000000e+00  0.000000e+00 "
    puts $id " 0.000000e+00  1.000000e+00  0.000000e+00  0.000000e+00 "
    puts $id " 0.000000e+00  0.000000e+00  1.000000e+00  0.000000e+00 "
    puts $id " 0.000000e+00  0.000000e+00  0.000000e+00  1.000000e+00 "
    puts $id "round"
    close $id
  } else {
    puts "tksurfer: [file tail $script]: register.dat (ID mat) already made"
  }
  unset pseudoregdat
  # pre-update interface (avoid force re-try), enable 3D ROI popup panel bottom
  set scandir $fsaveragescandir
  set rawdata $isession/$scandir/orig+orig.BRIK
  set regdat $isession/$scandir/register.dat
}

### listcmd for combobox hacked into controls popup (subset of listcmd_label)
# fsavgannot manual reabbrev since always from fsaverage (no setfile fsavgannot)
proc listcmd_fsavgannot { combo } {
  global env subject hemi labeldir

  set fullsub $env(SUBJECTS_DIR)/fsaverage
  set fullfilelist5 [lsort [glob -nocomplain $fullsub/$labeldir/$hemi-*.annot]]
  set fullfilelist6 [lsort [glob -nocomplain $fullsub/$labeldir/$hemi.*.annot]]
  # manually abbrev fsavgannot since this "~" always means fsaverage (!$subject)
  set abbrevlist "{==== CSURF ANNOT FILES ====}"
  foreach fullfile $fullfilelist5 {
    set abbrevlist "$abbrevlist ~/$labeldir/[file tail $fullfile]"
  }
  set abbrevlist "$abbrevlist {==== MGH ANNOT FILES ====}"
  foreach fullfile $fullfilelist6 {
    set abbrevlist "$abbrevlist ~/$labeldir/[file tail $fullfile]"
  }
  $combo subwidget listbox delete 0 end
  foreach abbrev $abbrevlist { $combo insert end $abbrev }
}

### select command for combobox: glob, re-extract annotinfix
proc select_fsavgannot { combo value } {
  global fsavgannot fsavgannotabbrev annotinfix env

  # manual glob fsavgannot (vs. setfile) since this "~" always means fsaverage
  if { [string range $value 0 0] == "/"} {
    set fsavgannot $value
  } elseif { [string range $value 0 0] == "~" &&
             [string range $value 1 1] == "/" } {
    set fsavgannot $env(SUBJECTS_DIR)/fsaverage/[string range $value 2 end]
  } else {  ;# non-abs, non-tilde relative: assume just tail
    set fullname $env(SUBJECTS_DIR)/fsaverage/label/$value
  }
  set annotinfix [string range [file rootname [file tail $fsavgannot]] 3 end]
}

### mk popup ctrls (N.B.: re-enters script on RUN SCRIPT), else cmdline readenv
# N.B.: varname diff w/tksurfer.tcl where *ctrls is popup proc, *ctrlswin is win
if ![info exists annot2roictrls] { set annot2roictrls "" }
if [winfo viewable .] {  ;# make popup
  set noexit 1
  if {!$userok} { ;# make/raise panel, return (i.e., not entered by RUN SCRIPT)
    if [winfo exists $annot2roictrls] {
      raise $annot2roictrls
    } else {
      set annot2roictrls [controls "SAMPLE FSAVERAGE ANNOTATION\
                                  \nTO AN INDIVIDUAL SUBJECT\
                                  \noptional: make 3D AFNI ROI's\
                                  \n(if sub is fsaverage, mk mgz parc)" {
        fsavgannotabbrev
        whitespace
        make_3D_AFNI_ROIs_flag
        isession
        scandir
        rawdata
        regdat
        whitespace
        whitespace
        erodesteps
        normdsampsearchflag normdfracflag
        normdsamp normdmax
        whitespace
        normdfracsamp normdfracmax
        whitespace
        savesingleROIbriksflag
        fill3Dholesflag
        neighfracthresh
      } "RUN SCRIPT" "set userok 1; source [info script]" 16]

      ### extensive hacks/customization to basic controls popup interface items
      ### hack1: repl controls-made entry w/filled tix dropdown w/fsavg annots
      pack forget $annot2roictrls.fsavgannotabbrev
      tixComboBox $annot2roictrls.cbx -label "annot:" -dropdown true \
        -editable true -variable fsavgannotabbrev \
        -listcmd "listcmd_fsavgannot $annot2roictrls.cbx" -listwidth 300 \
        -command "select_fsavgannot $annot2roictrls.cbx"
      $annot2roictrls.cbx subwidget label config -font $ffont -bg $bgcol
      $annot2roictrls.cbx subwidget entry config -font $hfont \
        -selectbackground $selbgcol -highlightbackground $bgcol -width 23
      $annot2roictrls.cbx subwidget listbox config -font $ffont \
        -selectbackground $selbgcol -selectforeground black
      pack $annot2roictrls.cbx -after $annot2roictrls.la -side top

      ### hack2: entry touch-ups
      $annot2roictrls.isession.la config -width 7
      $annot2roictrls.isession.e config -width 24  ;# see more of this path
      $annot2roictrls.isession.e xview moveto 1    ;# next 3: goto end
      $annot2roictrls.rawdata.e xview moveto 1   
      $annot2roictrls.regdat.e xview moveto 1

      ### hack3: ROIs Y/N enables/disables entries/ticks to guide user
      $annot2roictrls.ck0 config -command {  ;# make_3D_AFNI_ROIs_flag
        if {$make_3D_AFNI_ROIs_flag} {
          foreach z "isession scandir rawdata regdat erodesteps" {
            $annot2roictrls.$z.la config -state normal
            $annot2roictrls.$z.e config -state normal
          }
          if {$normdsampsearchflag} {
            if {$normdfracflag} {
              foreach z "normdfracsamp normdfracmax" {
                $annot2roictrls.$z.la config -state normal
                $annot2roictrls.$z.e config -state normal
              }
              foreach z "normdsamp normdmax" {
                $annot2roictrls.$z.la config -state disabled
                $annot2roictrls.$z.e config -state disabled
              }
            } else {
              foreach z "normdfracsamp normdfracmax" {
                $annot2roictrls.$z.la config -state disabled
                $annot2roictrls.$z.e config -state disabled
              }
              foreach z "normdsamp normdmax" {
                $annot2roictrls.$z.la config -state normal
                $annot2roictrls.$z.e config -state normal
              }
            }
          } else {
            foreach z "normdsamp normdmax normdfracsamp normdfracmax" {
              $annot2roictrls.$z.la config -state disabled
              $annot2roictrls.$z.e config -state disabled
            }
          }
          # independent of search state
          if {$fill3Dholesflag} {
            $annot2roictrls.neighfracthresh.la config -state normal
            $annot2roictrls.neighfracthresh.e config -state normal
          } else {
            $annot2roictrls.neighfracthresh.la config -state disabled
            $annot2roictrls.neighfracthresh.e config -state disabled
          }
          $annot2roictrls.ck1 config -state normal
          $annot2roictrls.ck2 config -state normal
          $annot2roictrls.ck3 config -state normal
        } else {
          foreach z "isession scandir rawdata regdat erodesteps \
              normdsamp normdmax normdfracsamp normdfracmax neighfracthresh" {
            $annot2roictrls.$z.la config -state disabled
            $annot2roictrls.$z.e config -state disabled
          }
          $annot2roictrls.ck1 config -state disabled
          $annot2roictrls.ck2 config -state disabled
          $annot2roictrls.ck3 config -state disabled
        }
        unset z
      }

      ### hack4: enable/disable sample limits
      $annot2roictrls.ck1 config -command {  ;# normdsampsearchflag
        if {$normdsampsearchflag && $make_3D_AFNI_ROIs_flag} {
          if {$normdfracflag} {
            foreach z "normdfracsamp normdfracmax" {
              $annot2roictrls.$z.la config -state normal
              $annot2roictrls.$z.e config -state normal
            }
            foreach z "normdsamp normdmax" {
              $annot2roictrls.$z.la config -state disabled
              $annot2roictrls.$z.e config -state disabled
            }
          } else {
            foreach z "normdfracsamp normdfracmax" {
              $annot2roictrls.$z.la config -state disabled
              $annot2roictrls.$z.e config -state disabled
            }
            foreach z "normdsamp normdmax" {
              $annot2roictrls.$z.la config -state normal
              $annot2roictrls.$z.e config -state normal
            }
          }
          $annot2roictrls.ck2 config -state normal
        } else {
          foreach z \
            "normdsamp normdmax normdfracsamp normdfracmax neighfracthresh" {
            $annot2roictrls.$z.la config -state disabled
            $annot2roictrls.$z.e config -state disabled
          }
          $annot2roictrls.ck2 config -state disabled
        }
        # separately (b/c && in initial if)
        if {$normdsampsearchflag} {
          $annot2roictrls.ck2 config -state normal
        } else {
          $annot2roictrls.ck2 config -state disabled
        }
        unset z
      }

      ### hack5: enable/disable correct pairs of sample limits
      $annot2roictrls.ck2 config -command {  ;# normdfracflag
        if {$normdsampsearchflag && $make_3D_AFNI_ROIs_flag} {
          if {$normdfracflag} {
            foreach z "normdfracsamp normdfracmax" {
              $annot2roictrls.$z.la config -state normal
              $annot2roictrls.$z.e config -state normal
            }
            foreach z "normdsamp normdmax" {
              $annot2roictrls.$z.la config -state disabled
              $annot2roictrls.$z.e config -state disabled
            }
          } else {
            foreach z "normdfracsamp normdfracmax" {
              $annot2roictrls.$z.la config -state disabled
              $annot2roictrls.$z.e config -state disabled
            }
            foreach z "normdsamp normdmax" {
              $annot2roictrls.$z.la config -state normal
              $annot2roictrls.$z.e config -state normal
            }
          }
        } else {
          foreach z "isession scandir rawdata regdat erodesteps \
                     normdsamp normdmax normdfracsamp normdfracmax" {
            $annot2roictrls.$z.la config -state disabled
            $annot2roictrls.$z.e config -state disabled
          }
        }
        unset z
      }

      ### hack6: enable/disable neighfracthresh
      $annot2roictrls.ck3 config -command {  ;# neighfracthresh
        if {$fill3Dholesflag} {
           $annot2roictrls.neighfracthresh.la config -state normal
           $annot2roictrls.neighfracthresh.e config -state normal
        } else {
           $annot2roictrls.neighfracthresh.la config -state disabled
           $annot2roictrls.neighfracthresh.e config -state disabled
        }
      }

      ### inits (N.B.: vars may be in non-default state from prev panel open)
      # init fsavgannot and its abbrev, maybe re-extract annot infix
      # don't use setfile (for indiv subj) since "~" here always means fsaverage
      if {"$fsavgannotabbrev" == 0} {  ;# from controls proc create var
        # next is default csurf-style (vs. dot)
        set fsavgannot \
          $env(SUBJECTS_DIR)/fsaverage/label/$hemi-$annotinfix.annot
        set fsavgannotabbrev ~/label/$hemi-$annotinfix.annot
      } else {  ;# re-extract annotinfix (if re-run)
        set annotinfix \
          [string range [file rootname [file tail $fsavgannot]] 3 end]
      }
      # panel vars (override tksurfer defaults on panel create)
      set normdsampsearchflag 1
      logcmd "set normdsampsearchflag 1"
      set normdfracflag 1
      logcmd "set normdfracflag 1"
      set normdfracsamp 0.0
      logcmd "set normdfracsamp 0.0"
      set normdfracmax 1.0
      logcmd "set normdfracmax 1.0"
      # force on 3D ROIs tickbox if fsaverage
      if [string match fsaverage $subject] {
        set make_3D_AFNI_ROIs_flag 1
      }
      # main init enable/disables
      if {$make_3D_AFNI_ROIs_flag} {
        foreach z "isession scandir rawdata regdat erodesteps" {
          $annot2roictrls.$z.la config -state normal
          $annot2roictrls.$z.e config -state normal
        }
        if {$normdsampsearchflag} {
          if {$normdfracflag} {
            foreach z "normdfracsamp normdfracmax" {
              $annot2roictrls.$z.la config -state normal
              $annot2roictrls.$z.e config -state normal
            }
            foreach z "normdsamp normdmax" {
              $annot2roictrls.$z.la config -state disabled
              $annot2roictrls.$z.e config -state disabled
            }
          } else {
            foreach z "normdfracsamp normdfracmax" {
              $annot2roictrls.$z.la config -state disabled
              $annot2roictrls.$z.e config -state disabled
            }
            foreach z "normdsamp normdmax" {
              $annot2roictrls.$z.la config -state normal
              $annot2roictrls.$z.e config -state normal
            }
          }
          $annot2roictrls.ck2 config -state normal
        } else {
          foreach z \
            "normdsamp normdmax normdfracsamp normdfracmax" {
            $annot2roictrls.$z.la config -state disabled
            $annot2roictrls.$z.e config -state disabled
          }
          $annot2roictrls.ck2 config -state disabled
        }
        $annot2roictrls.ck1 config -state normal
        $annot2roictrls.ck3 config -state normal
      } else {
        foreach z "isession scandir rawdata regdat erodesteps \
                   normdsamp normdmax normdfracsamp normdfracmax" {
          $annot2roictrls.$z.la config -state disabled
          $annot2roictrls.$z.e config -state disabled
        }
        $annot2roictrls.ck1 config -state disabled
        $annot2roictrls.ck3 config -state disabled
      }
      # independent of search state
      if {$fill3Dholesflag && $make_3D_AFNI_ROIs_flag} {
         $annot2roictrls.neighfracthresh.la config -state normal
         $annot2roictrls.neighfracthresh.e config -state normal
      } else {
         $annot2roictrls.neighfracthresh.la config -state disabled
         $annot2roictrls.neighfracthresh.e config -state disabled
      }
      unset z 

      # help
      bind $annot2roictrls <ButtonRelease-3> { helpwin script_annot2roi }
      ### end controls proc hacks

      ### open samp dist popup, mv up unoverlap (forgot needed already there!)
      #set sampclustctrlswin [sampclustctrls]
      #set sampclustgeom [split [wm geometry $sampclustctrlswin] "+"]
      #wm geometry $sampclustctrlswin \
      #  +[lindex $sampclustgeom 1]+[expr [lindex $sampclustgeom 2]-535]
      #unset sampclustgeom
    }
    return
  } ;# else fall through to run script
} else {                   ;# batch scripts; re-read env to override defaults
  source $env(CSURF_DIR)/lib/tcl/readenv.tcl
}

### check input annot (listcmd has already checked, but in case entry edited) 
# next: get and glob current fsavgannotabbrev in case no <Ret> in combo
select_fsavgannot $annot2roictrls.cbx [$annot2roictrls.cbx subwidget entry get]
if ![file exists $fsavgannot] {
  puts "tksurfer: [file tail $script]: ### $fsavgannot not found"
  if [winfo viewable .] {  ;# tcl tools window
    confirmalert "fsaverage annotation file (surface ROIs):\
              \n\n    $fsavgannot\
              \n\nnot found"
    return
  } else { exit }  ;# cmdline script
}

### check single subj sphere.reg there
if ![file exists $env(SUBJECTS_DIR)/$subject/surf/$hemi.sphere.reg] {
  puts "tksurfer: [file tail $script]: ### subject $hemi.sphere.reg not found"
  if [winfo viewable .] {  ;# tcl tools window
    confirmalert "$hemi.sphere.reg not found for $subject"
    return
  } else { exit }  ;# cmdline script
}

### check output annot (script overwrites, interactive req's confirm overwrite)
set sep [string range [file tail $fsavgannot] 2 2]  ;# '.' or '-' only
set subjannot $env(SUBJECTS_DIR)/$subject/label/${hemi}${sep}${annotinfix}.annot
if ![string match fsaverage $subject] {
  set overwrite_annot 1
  if [file exists $subjannot] {
    if [winfo viewable .] {
      set action [okreplace $subjannot \
                   "Surf2surf Resample: fsaverage -> single subject annotation:\
                \n\n    [file tail $subjannot]\
                \n\nalready exists.\
                \n\nUse it, or resample/overwrite?" "Redo" "Use Existing"]
      if {$action == 0} {unset subjannot overwrite_annot; return};#ca
      if {$action == 1} {set overwrite_annot 1}                 ;# overwrite
      if {$action == 2} {set overwrite_annot 0}                 ;# use existing
    }
    puts "tksurfer: [file tail $script]: ### overwriting single subj resample:"
    puts "tksurfer: [file tail $script]:  $subjannot"
  }
}

### go1: resamp fsaverage annot to this sub w/mri_surf2surf (fsaverage: skip)
if ![string match fsaverage $subject] {
  set cmd ""
  if {$overwrite_annot} {
    puts "tksurfer: [file tail $script]: resample fsaverage annot to this subj"
    # assume mri_surf2surf on path (since tksurfer is)
    set cmd "mri_surf2surf \
      --srcsubject fsaverage \
      --trgsubject $subject \
      --hemi $hemi \
      --mapmethod nnf \
      --sval-annot $fsavgannot \
      --tval $subjannot"
    catch { puts [eval exec $cmd] } ret
    if {$ret != ""} {puts "tksurfer: [file tail $script]: ### scripterr: $ret"}
    logcmd "eval exec $cmd"
    puts "tksurfer: [file tail $script]: resampled annotation written to:"
    puts "tksurfer: [file tail $script]:  $subjannot"
    puts "tksurfer: [file tail $script]: --------------------------------"
    if [winfo viewable .] {
      confirmalert "[file tail $script]: fsaverage annotation:\
                \n\n    [file tail $fsavgannot]\
                \n\nresampled to $subject and written to:\
                \n\n    $subjannot"
    }
    puts "tksurfer: [file tail $script]: mri_surf2surf cmd:"
    puts "tksurfer:  $cmd"

  } else {
    puts "tksurfer: [file tail $script]: use existing [file tail $subjannot]"
  }
  unset cmd overwrite_annot
} else {  ;# fsaverage special case
  if [winfo viewable .] {
    puts "tksurfer: [file tail $script]: skip resamp fsaverage annot to itself"
    confirmalert "[file tail $script]: fsaverage annotation:\
              \n\n    [file tail $fsavgannot]\
              \n\nis already on fsaverage: skipping resample"
  }
}
# check/warn if opposite hemi not done
if {$hemi == "rh"} { set ophemi lh }
if {$hemi == "lh"} { set ophemi rh }
set opannot $env(SUBJECTS_DIR)/$subject/label/${ophemi}${sep}${annotinfix}.annot
if { [winfo viewable .] && ![string match fsaverage $subject] } {
  if ![file exists $opannot] {
    confirmalert "N.B.: $annotinfix not yet resampled to to OPPOSITE hemi:\
              \n\n    $opannot\
              \n\nnot found\
              \n\n(separate *.annot for each hemi)"
  }
}
unset opannot ophemi

### maybe return/exit after just resample .annot
if {!$make_3D_AFNI_ROIs_flag} {  ;# copy of cleanup below
  puts "tksurfer: [file tail $script]: skip mk 3D ROI BRIKs from resamp'd annot"
  if ![info exists noexit] { exit }  ;# cmdline script
  set userok 0
  #if [info exists annot2roictrls] {destroy $annot2roictrls} ;#leave up for redo
  unset subjannot
  return   ;# else catch in tksurfer.tcl returns err (=last return of last cmd)
}

### now check 3D ROI args (regular sub vs. fsaverage)
if ![string match fsaverage $subject] {
  if { [file tail $isession] == "__nosession__" ||
       $scandir == "__noscandir__" || 
       ![file exists $isession/$scandir] } {
    puts "tksurfer: [file tail $script]: bad session or scandir for ROI model:\
        \n    session = $isession\
        \n    scandir = $scandir"
    if [winfo viewable .] {  ;# tcl tools window
      confirmalert "[file tail $script]: bad session or scandir:\
                \n\n    session = $isession\
                  \n    scandir = $scandir\
                \n\nEnter valid session/scandir, or pick existing w/csurf\
                  \nusing upper right \"Functional:\" dropdowns:\
                \n\n    1) select from \"session:\"\
                  \n    2) select from \"scandir:\""
      return
    } else { exit }  ;# cmdline script
  }
  if { ![file exists $rawdata] || ![file exists $regdat] } {
    puts "tksurfer: [file tail $script]: bad rawdata or regdat:\
        \n    rawdata = $rawdata\
        \n    regdat = $regdat"
    if [winfo viewable .] {  ;# tcl tools window
      confirmalert "[file tail $script]: bad rawdata or regdat:\
                \n\n    rawdata = $rawdata\
                  \n    regdata = $regdat\
                \n\nNeed 1 rawdata scan + register.dat to sample surf->3D:\
                \n\n    1) File -> New Functional\
                  \n    2) SessionTools -> File Make Scandirs, Find/Copy Raw\
                  \n    3) SessionTools -> Setup Align/Funct Scans\
                  \n           Funct Scan Dir\
                  \n           READ HEADER\
                  \n           INIT/FLIP\
                  \n           FUNCT=>SUBJ"
      return
    } else { exit }  ;# cmdline script
  }
} else {  ;# fsaverage
  if { "$scandir" != "$fsaveragescandir" } {
    if [winfo viewable .] {  ;# tcl tools window
      confirmalert "\$scandir not \"$fsaveragescandir\""
      return
    } else { exit }  ;# cmdline script
  }
  if { "$rawdata" != "$isession/$scandir/orig+orig.BRIK" } {
    if [winfo viewable .] {  ;# tcl tools window
      confirmalert "\$rawdata not:\
                 \n\n$isession/$scandir/orig+orig.BRIK:\
                 \n\n$rawdata"
      return
    } else { exit }  ;# cmdline script
  }
  if { "$regdat" != "$isession/$scandir/register.dat" } {
    if [winfo viewable .] {  ;# tcl tools window
      confirmalert "\$regdat not:\
                 \n\n$isession/$scandir/register.dat:\
                 \n\n$regdat"
      return
    } else { exit }  ;# cmdline script
  }
}

### if fsaverage, ask clear prev ROI BRIKs
# N.B.: would rm single sub funct! (can't know prev $sep to make more specific)
if [string match fsaverage $subject] {
  set list [glob -nocomplain $isession/$scandir/$hemi*.BRIK]
  if {"$list" != ""} {
    set shortlist "[lindex $list 0]\n[lindex $list 1]\n[lindex $list 2]\n. . ."
    if [okreplace "" "OK to clear all prev 3D ROIs for this hemisphere\
                   \n(hemi = $hemi) in $scandir scandir?\
                 \n\n$shortlist" \
                   "Clear 1-pesudofunct (hemi=$hemi) 3D ROIs"] {
       foreach file $list { exec rm -f $file }
       set list [glob -nocomplain $isession/$scandir/$hemi*.HEAD]
       foreach file $list { exec rm -f $file }
    }
    unset shortlist
  }
  unset list
}

### final 3D ROIs bug-out chance
if ![okreplace "" "OK to generate 3D ROIs plus all-in-one BRIK\
                 \nfor following annotation?\
               \n\n    $fsavgannot\
               \n\nTakes ~2 sec for each annotation region\
               \n\nN.B.: will overwrite any same-named BRIKs in:\
               \n\n    $isession/$scandir" \
               "Make 3D ROIs"] { return }

### go2: expand tksurfer abbreviations (only needed for standalone script)
uplevel #0 "setfile regdat $regdat"
logcmd "setfile regdat $regdat"
uplevel #0 "setfile rawdata $rawdata"
logcmd "setfile rawdata $rawdata"

### load, maybe erode annotation
puts "tksurfer: [file tail $script]: load/convert annot to 3D ROI's"
# load resampled annot
clear_annot
logcmd "clear_annot"
redrawbutton    ;# no GL win: OK
# anlabel (used by read_mgh_annot) is curr subj (resampled *or* fsaverage) annot
setfile anlabel $subjannot
logcmd "setfile anlabel $subjannot"
read_mgh_annot  ;# reads current $anlabel
logcmd "read_mgh_annot"
set_annot_alpha 255
logcmd "set_annot_alpha 255"
set annotbordflag 0
logcmd "set annotbordflag 0"
set labelflag 1
logcmd "set labelflag 1"
set overlayflag 1 
logcmd "set overlayflag 1"
set surfcolor 1
logcmd "set surfcolor 1"
redrawbutton    ;# no GL win: OK
# maybe erode
for {set i 0} {$i < $erodesteps} {incr i} {
  erode_annot
  logcmd "erode_annot"
  redrawbutton
}

### convert annot to indiv 3D ROI brik's, including all-in-one
# load sampling surface (speeds up write_annotcols_timecourses_stats)
set insurfCURR $insurf
logcmd "set insurfCURR $insurf"
setfile insurf $hemi.orig
logcmd "setfile insurf $hemi.orig"
read_binary_surface
logcmd "read_binary_surface"
# sample surface annot's to ROI BRIKs, make all-in-one BRIK
write_annotcols_timecourses_stats 3     ;# 3=3D-ROIs
logcmd "write_annotcols_timecourses_stats 3"
# restore init surface
setfile insurf $insurfCURR
logcmd "setfile insurf $insurfCURR"
read_binary_surface
logcmd "read_binary_surface"
redrawbutton

### N.B.: keep parallel to name-gen C code in write_annotcols_timecourses_stats
if {!$normdfracflag} {
  set inf [format "mm=%1.1fto%1.1f" $normdsamp $normdmax]
} else {
  set inf [format "fr=%1.1fto%1.1f" $normdfracsamp $normdfracmax]
}

### optionally patch pial surface holes in all-in-one BRIK
if {$fill3Dholesflag} {
  puts "tksurfer: [file tail $script]: fill holes in BRIKs"
  if [winfo viewable .] {
    confirmalert "[file tail $script]: fill holes in BRIKs\
             \n\n(~3 sec per region)"
  }
  set brk $isession/$scandir/$hemi-ALL_ANNOT_ROIs-$inf+orig.BRIK
  fill_idnumbrik_holes $brk $neighfracthresh
  # next list will be empty w/default savesingleROIbriksflag=0
  set list \
    [glob -nocomplain $isession/$scandir/$hemi-region_*.label-$inf+orig.BRIK]
  foreach brk $list { fill_idnumbrik_holes $brk $neighfracthresh }
  unset list brk
} else { puts "tksurfer: [file tail $script]: skip fill BRIK holes" }

### explain outputs
puts "tksurfer: [file tail $script]: outputs in $isession/${scandir}:"
puts "tksurfer: [file tail $script]:   $hemi-<ROI_1>-$inf+orig.BRIK"
puts "tksurfer: [file tail $script]:   $hemi-<ROI_2>-$inf+orig.BRIK"
puts "tksurfer: [file tail $script]:   ..."
puts \
 "tksurfer: [file tail $script]:   $hemi-ALL_ANNOT_ROIs-$inf+orig.BRIK"
puts "tksurfer: [file tail $script]: done"
if [winfo viewable .] {
  confirmalert "[file tail $script]: 3D ROI output files written to:\
            \n\n    $isession/${scandir}:\
            \n\n        $hemi-<ROI_1>-$inf+orig.BRIK\
              \n        $hemi-<ROI_2>-$inf+orig.BRIK\
              \n        ...\
              \n        $hemi-ALL_ANNOT_ROIs-$inf+orig.BRIK"
}

### if both hemi ALL-ROIs BRIKs merge (if fsavg conv to fsaverage/mri mgz parc)
set lh_brk   $isession/$scandir/lh-ALL_ANNOT_ROIs-$inf+orig.BRIK
set rh_brk   $isession/$scandir/rh-ALL_ANNOT_ROIs-$inf+orig.BRIK
set both_brk $isession/$scandir/ALL_ANNOT_ROIs-$inf+orig.BRIK
set rh_mgz   $env(SUBJECTS_DIR)/$subject/mri/rh-$annotinfix.mgz
set lh_mgz   $env(SUBJECTS_DIR)/$subject/mri/lh-$annotinfix.mgz
set both_mgz $env(SUBJECTS_DIR)/$subject/mri/$annotinfix.mgz
if { [file exists $lh_brk] && [file exists $rh_brk] } {
  puts "tksurfer: [file tail $script]: merge right/left ROI BRIKs"
  if [winfo viewable .] {
    confirmalert "Found both right and left idnum BRIK's:\
              \n\n    $lh_brk\
                \n    $rh_brk\
              \n\nmerge right/left all-in-one BRIK's to:\
              \n\n    $both_brk"
  }
  merge_idnum_briks $lh_brk $rh_brk $both_brk
  logcmd "merge_idnum_briks $lh_brk $rh_brk $both_brk"
  if [string match fsaverage $subject] {
    puts "tksurfer: [file tail $script]: convert merge R/L BRIK to mgz parc"
    if [winfo viewable .] {
      confirmalert "Convert merged R/L BRIK to mgz parc in fsaverage/mri:\
                \n\n    $both_mgz"
      shortcorbrik2intmgz $both_brk $both_mgz
      logcmd "shortcorbrik2intmgz $both_brk $both_mgz"
    }
  }
} else {  ;# skip merge (and convert)
  if [winfo viewable .] {
    puts "tksurfer: [file tail $script]: idnum BRIK's for both hemis not found"
    if [string match fsaverage $subject] {
      puts "tksurfer: [file tail $script]: skip merge R/L and convert it to mgz"
      confirmalert "[file tail $script]: idnum BRIK's for both hemis NOT found\
                 \nLooked for:\
               \n\n    $isession/$scandir/{rh,lh}-ALL_ANNOT_ROIs-$inf+orig.BRIK\
               \n\nskip merge right/left and convert it to mgz"
    } else {
      puts "tksurfer: [file tail $script]: skip merge R/L"
      confirmalert "[file tail $script]: idnum BRIK's for both hemis NOT found\
                 \nLooked for:\
               \n\n  $isession/$scandir/{rh,lh}-ALL_ANNOT_ROIs-$inf+orig.BRIK\
               \n\nskip merge right/left"
    }
  }
}
unset lh_brk rh_brk both_brk rh_mgz lh_mgz both_mgz
confirmalert "Done"

### cleanup
if ![info exists noexit] { exit }  ;# default for command line script
set userok 0
#if [info exists annot2roictrls] {destroy $annot2roictrls}  ;#leave up for redo
foreach var "subjannot insurfCURR cmd i" {  ;# cleanup
  if [info exists $var] { unset $var }
}
return   ;# else catch in tksurfer.tcl returns err (=last return of last cmd)

